How to map and store countries and currencies in JavaScript Array - javascript

I have three different currencies and each currency is mapped to multiple countries. The third currency(EUR) is mapped to several countries. How can I structure my data in a javascript array to easily get the corresponding currency code by country. I have the following data, what is the best way to structure to easily access it with country code.
USD - en-US,es-MX
GBP - en-GB
EUR - de-AT,nl-BE,el-CY,et-EE,fi-FI,fr-FR,de-DE,el-GR,en-IE

You could use an object, its constant time lookup, as opposed to an array that you would have to loop over:
var currencies = {
'de-AT': 'EUR',
'nl-BE': 'EUR'
...
}
If you use an array:
var currencies = {
'USD': ['en-US', 'es-MX']
...
}
While it might look cleaner, and easier to make, it will be slower, as you would have to loop through each array to check if the item is there

Practically you can do a re-map operation like this;
var data = {
USD : ["en-US","es-MX"],
GBP : ["en-GB"],
EUR : ["de-AT","nl-BE","el-CY","et-EE","fi-FI","fr-FR","de-DE","el-GR","en-IE"]
},
curMap = {};
Object.keys(data).forEach(k => data[k].forEach(c => curMap[c] = k));
console.log(curMap);

Related

Filter one list using other list in fastest way?

I have one list of objects of Food with fields name and price.
I have other list of objects of Category with fields food_name and its category_name.
Now, I want to filter the first list according to the category_name in the second list. How can I do it in fastest way possible?
I am tagging few languages because I just need the filtering logic on any language.
For e.g. in Dart
List<Food> foods = [Food(name: 'Mango', price: 50), Food(name: 'Cucumber', price: 100)];
List<Category> categories = [Category(name: 'Fruits', foodName: 'Mango'), Category(name: 'Vegetables', foodName: 'Cucumber') ];
I want to filter the list of foods according to category name from second list in fastest way possible.
Using two lists this will cost you O(n^2) time, you should instead consider using a map structure. In Kotlin this can be done as
val map = foodList.associateBy { it.name }
val result = mutableListOf<Food>()
categoryList.forEach {
if(map.containsKey(it.foodName)) { result.add(map[it.foodName]) }
}

Get "leaderboard" of list of numbers

I am trying to get a kind of "leaderboard" from a list of numbers. I was thinking of making an array with all the numbers like this
var array = [];
for (a = 0; a < Object.keys(wallets.data).length; a++) { //var wallets = a JSON (parsed) response code from an API.
if (wallets.data[a].balance.amount > 0) {
array.push(wallets.data[a].balance.amount)
}
}
//Add some magic code here that sorts the array into descending numbers
This is a great option, however I need some other values to come with the numbers (one string). That's why I figured JSON would be a better option than an array.
I just have no idea how I would implement this.
I would like to get a json like this:
[
[
"ETH":
{
"balance":315
}
],
[
"BTC":
{
"balance":654
}
],
[
"LTC":
{
"balance":20
}
]
]
And then afterwards being able to call them sorted descending by balance something like this:
var jsonarray[0].balance = Highest number (654)
var jsonarray[1].balance = Second highest number (315)
var jsonarray[2].balance = Third highest number (20)
If any of you could help me out or point me in the right direction I would appreciate it greatly.
PS: I need this to happen in RAW JS without any html or libraries.
You should sort the objects before making them a JSON. You can write your own function or use a lambda. See this [https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value]
Since you are dealing with cryptocurrency you can use the currency-code as a unique identifier.
Instead of an array, you can define an object with the currency as properties like this:
const coins = {
ETH: [300, 200, 500],
BTC: [20000, 15000, 17000]
}
then you can access each one and use Math.max or Math.min to grab the highest / lowest value of that hashmap. E.G. Math.max(coins.BTC)
And if you need to iterate over the coins you have Object.keys:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Thank you all for your answer. I ended up using something like:
leaderboard = []
for (a = 0; a < Object.keys(wallets.data).length; a++) {
if (wallets.data[a].balance.amount > 0) {
leaderboard.push({"currency":wallets.data[a].balance.currency, "price":accprice}) //accprice = variable which contains the value of the userhold coins of the current coin in EUR
}
}
console.log(leaderboard.sort(sort_by('price', true, parseInt)));

Group by in javascript or angularjs

I just want to do sum value column based on the Year and my data is below, but I don't know how to do this either using angular(in script) or javascript.
[
{"Year":2013,"Product":"A","Value":0},
{"Year":2013,"Product":"B","Value":20},
{"Year":2013,"Product":"A","Value":50},
{"Year":2014,"Product":"D","Value":55},
{"Year":2014,"Product":"M","Value":23},
{"Year":2015,"Product":"D","Value":73},
{"Year":2015,"Product":"A","Value":52},
{"Year":2016,"Product":"B","Value":65},
{"Year":2016,"Product":"A","Value":88}
]
I want to perform the sum on Value column and remove Product column as well.
Thanks
Edit As commenters have pointed out, this doesn't even require Lodash. Been using Lodash so much for current project I forgot reduce is built in. :-)
Also updated to put data in desired form [{"yyyy" : xxxx},...].
This code will accomplish this:
var data = [{"Year":2013,"Product":"A","Value":0},{"Year":2013,"Product":"B","Value":20},{"Year":2013,"Product":"A","Value":50},{"Year":2014,"Product":"D","Value":55},{"Year":2014,"Product":"M","Value":23},{"Year":2015,"Product":"D","Value":73},{"Year":2015,"Product":"A","Value":52},{"Year":2016,"Product":"B","Value":65},{"Year":2016,"Product":"A","Value":88}];
var sum = data.reduce(function(res, product){
if(!(product.Year in res)){
res[product.Year] = product.Value;
}else{
res[product.Year] += product.Value;
}
return res;
}, {});
result = [];
for(year in sum){
var tmp = {};
tmp[year] = sum[year];
result.push(tmp);
}
console.log(result);
RESULT:
[{"2013" : 70}, {"2014" : 78}, {"2015" : 125}, {"2016" : 153}]
ORIGINAL ANSWER
The easiest way I can think of to do this is with the Lodash Library. It gives you some nice functional programming abilities like reduce, which basically applies a function to each element of an array or collection one by one and accumulates the result.
In this case, if you use Lodash, you can accomplish this as follows:
var data = [{"Year":2013,"Product":"A","Value":0},{"Year":2013,"Product":"B","Value":20},{"Year":2013,"Product":"A","Value":50},{"Year":2014,"Product":"D","Value":55},{"Year":2014,"Product":"M","Value":23},{"Year":2015,"Product":"D","Value":73},{"Year":2015,"Product":"A","Value":52},{"Year":2016,"Product":"B","Value":65},{"Year":2016,"Product":"A","Value":88}];
result = _.reduce(data, function(res, product){
if(!(product.Year in res)){
res[product.Year] = product.Value;
}else{
res[product.Year] += product.Value;
}
return res;
}, {});
This yields:
{
"2013": 70,
"2014": 78,
"2015": 125,
"2016": 153
}
Basically, what we're telling Lodash is that we want to go through all the elements in data one by one, performing some operation on each of them. We're going to save the results of this operation in a variable called res. Initially, res is just an empty object because we haven't done anything. As Lodash looks at each element, it checks if that Product's year is in res. If it is, we just add the Value to that year in res. If it's not, we set that Year in res to the Value of the current product. This way we add up all the product values for each year.
If you want to try it out you can do it here:
Online Lodash Tester
Cheers!
You could do this using plain JavaScript. We use an object that will hold the results and the forEach array method. The object that would hold the results would have as keys the years and as values the sums of the corresponding values.
var data = [
{"Year":2013,"Product":"A","Value":0},
{"Year":2013,"Product":"B","Value":20},
{"Year":2013,"Product":"A","Value":50},
{"Year":2014,"Product":"D","Value":55},
{"Year":2014,"Product":"M","Value":23},
{"Year":2015,"Product":"D","Value":73},
{"Year":2015,"Product":"A","Value":52},
{"Year":2016,"Product":"B","Value":65},
{"Year":2016,"Product":"A","Value":88}
];
groupedData = {};
data.forEach(function(item){
var year = item.Year;
var value = item.Value;
if(groupedData.hasOwnProperty(year)){
groupedData[year]+=value;
}else{
groupedData[year]=value;
}
});
console.log(groupedData);

JS and ExpressionEngine - Remove KV pairs by duplicate values only?

We're building a site with ExpressionEngine. We are running a SQL query to gather up all member IDs for a specific member group. After that, we are using EE tags to get data from a custom member field for each member ID.
The ID and field data need to stay paired, as we will be populating a drop-down so that the ID is the value and the field data is the text, so we are currently putting them into a JS array as key/value pairs. The call is as follows:
var array= [
{exp:query sql="SELECT * FROM exp_members WHERE group_id = 5"}
{exp:member:custom_profile_data
member_id="{member_id}"}
{if company != ''}
{{member_id}:"{company}"},
{/if}
{/exp:member:custom_profile_data}
{/exp:query}
};
This gives us the output:
var array = [
{1:"name01"},
{2:"name02"},
{3:"name01"},
{4:"name03"}
];
Now, our problem. We need to remove objects based on duplicate field data (values) only, so the above array would look like this:
var array = [
{1:"name01"},
{2:"name02"},
{4:"name03"}
];
None of these IDs (keys) will ever be the same, but the field data (values) can be. So we want to keep the first KV pair that comes through with a unique value, but remove any subsequent dupes of that value - despite the fact that they will not be true "duplicate values" due to a different ID (key).
Keeping in mind that the KV pairs are all dynamic, is there any possible way to do this via JS so we can create a new array for the cleaned data to pass to the drop-down?
You could handle the duplications by modifying your MySQL query. (In my example, my custom field ID was 1.)
var myArray = [];
{exp:query sql="SELECT MIN(m.member_id) AS co_member_id, d.m_field_id_1 AS company FROM exp_members m INNER JOIN exp_member_data d ON m.member_id = d.member_id WHERE d.m_field_id_1 != '' AND m.group_id > 0 GROUP BY d.m_field_id_1;"}
myArray.push({{co_member_id}: "{company}"});
{/exp:query}
This query would use the first (in the ordinal sense) member_id found; you could also change the MIN to MAX and get the last.
This will give you a clean output in your source, without the need for any additional JS processing. I'd also recommend changing the names of the variables you're outputting as to not conflict in EE's parsing.
I would do it like...
function removeDups(arry){
var tmp = {}, retainIdx=[], newArry=[];
arry.forEach(function(obj, idx){
var val = obj[Object.keys(obj)[0]];
if(val && !tmp[val]){
retainIdx.push(idx);
tmp[val] = true;
}
});
retainIdx.forEach(function(i){
newArry.push(arry[i]);
});
return newArry;
};

Better data structure to handle this array

I have an array of data get from the server(ordered by date):
[ {date:"2012-8", name:"Tokyo"}, {date:"2012-3", name:"Beijing"}, {date:"2011-10", name:"New York"} ]
I'd like to :
get the name of the first element whose date is in a given year, for example, given 2012, I need Tokyo
get the year of a given name
change the date of a name
which data structure should I use to make this effective ?
because the array could be large, I prefer not to loop the array to find something
Since it appears that the data is probably already sorted by descending date you could use a binary search on that data to avoid performing a full linear scan.
To handle the unstated requirement that changing the date will then change the ordering, you would need to perform two searches, which as above could be binary searches. Having found the current index, and the index where it's supposed to be, you can use two calls to Array.splice() to move the element from one place in the array to another.
To handle searches by name, and assuming that each name is unique, you should create a secondary structure that maps from names to elements:
var map = {};
for (var i = 0, n = array.length; i < n; ++i) {
var name = array[i].name;
map[name] = array[i];
}
You can then use the map array to directly address requirements 2 and 3.
Because the map elements are actually just references to the array elements, changes to those elements will happen in both.
Assuming you are using unique cities, I would use the city names as a map key:
cities = {
Tokyo: {
date: "2012-8"
},
New York: {
date: "2011-10"
}
}
To search by date:
function byDate(date) {
for(el in cities) {
if(cities.hasOwnProperty(el) && cities[el].date === date)
return el;
}
}
Just for the record: without redesigning your date structure you could use sorting combined with the Array filter or map method:
function sortByDate(a,b){
return Number(a.date.replace(/[^\d]+/g,'')) >
Number(b.date.replace(/[^\d]+/g,''));
}
var example = [ {date:"2012-8", name:"Tokyo"},
{date:"2012-3", name:"Beijing"},
{date:"2011-10", name:"New York"} ]
.sort(sortByDate);
//first city with year 2012 (and the lowest month of that year)
var b = example.filter(function(a){return +(a.date.substr(0,4)) === 2012})[0];
b.name; //=> Beijing
//year of a given city
var city = 'Tokyo';
var c = example.filter(function(a){return a.city === city;})[0];
c.year; //=> 2012
//change year of 'New York', and resort data
var city = 'New York', date = '2010-10';
example = example.map(
function(a){if (a.name === city) {a.date = date;} return a;}
).sort(sortByDate);

Categories

Resources