I have this array:
[ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'DOLLAR', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ]
and I want to merge the content so that I will have:
[ [ 'TWENTY', 60 ],
[ 'TEN', 20 ],
[ 'FIVE', 15 ],
[ 'DOLLAR', 1 ],
[ 'QUARTER', 0.50 ],
[ 'DIME', 0.2 ],
[ 'PENNY', 0.04 ]]
I tried iterating through the array and summing values but had no success.
Really appreciate your help.
Mattia P
You can do this in one loop with an object as a map:
const array = [ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'DOLLAR', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ];
const result = array.reduce((map,[key,val]) => {
map[key] = (map[key] || 0) + val;
return map;
}, {});
console.log(Object.entries(result));
Object.entries(result) turns it from a nice object that you can access like result.PENNY back into the array format you want. You may find it easier to use as the map, in which case simply omit the Object.entries(...).
Using .reduce() and .find() you can group by the first element of the inner array.
Try as the following:
const array = [ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'DOLLAR', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ];
const result = array.reduce((a, c) => {
const found = a.find(f => f[0] === c[0]);
if (found) found[1] += c[1];
else a.push(c);
return a;
}, []);
console.log(result);
I hope this helps!
You could take a single line approach with a Map.
var data = [['TWENTY', 20], ['TWENTY', 20], ['TWENTY', 20], ['TEN', 10], ['TEN', 10], ['FIVE', 5], ['FIVE', 5], ['FIVE', 5], ['DOLLAR', 1], ['QUARTER', 0.25], ['QUARTER', 0.25], ['DIME', 0.1], ['DIME', 0.1], ['PENNY', 0.01], ['PENNY', 0.01], ['PENNY', 0.01], ['PENNY', 0.01]],
result = Array.from(data.reduce((m, [k, v]) => m.set(k, (m.get(k) || 0) + v), new Map));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
const a = [['TWENTY', 20],
['TWENTY', 20],
['TWENTY', 20],
['TEN', 10],
['TEN', 10],
['FIVE', 5],
['FIVE', 5],
['FIVE', 5],
['DOLLAR', 1],
['QUARTER', 0.25],
['QUARTER', 0.25],
['DIME', 0.1],
['DIME', 0.1],
['PENNY', 0.01],
['PENNY', 0.01],
['PENNY', 0.01],
['PENNY', 0.01]];
const b = {};
const c = [];
for (const [name, value] of a) {
if (!b[name]) {
b[name] = 0;
}
b[name] = b[name] + value
}
for (const [key, value] of Object.entries(b)) {
c.push([key, value])
}
console.log(c)
You can do it by using reduce and findIndex.
const data = [[ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TEN', 10 ], [ 'TEN', 10 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'DOLLAR', 1 ], [ 'QUARTER', 0.25 ], [ 'QUARTER', 0.25 ], [ 'DIME', 0.1 ], [ 'DIME', 0.1 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ]];
const res = data.reduce((a, [k, v]) => {
let index = a.findIndex(x => x[0] === k);
if (index === -1) {
a.push([k, v]);
} else {
a[index][1] += v;
}
return a;
}, []);
console.log(res);
.as-console-wrapper {
min-height: 100% !important;
top: 0;
}
This solution only with one iteration:
const array = [ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'FIVE', 5 ],
[ 'DOLLAR', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ];
let result = {};
array.forEach(item => {
if(result[item[0]]) {
result[item[0]][1] +=item[1]
} else {
result[item[0]] = item;
}
})
console.log(result)
If you want to abstract this to a simple function, it might look like this:
const total = array => Object .entries (array .reduce (
(acc, [name, val]) => ({...acc, [name]: (acc [name] || 0) + val})
, {}
))
const array = [ [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TEN', 10 ], [ 'TEN', 10 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'DOLLAR', 1 ], [ 'QUARTER', 0.25 ], [ 'QUARTER', 0.25 ], [ 'DIME', 0.1 ], [ 'DIME', 0.1 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ] ];
console .log (total (array))
.as-console-wrapper {min-height: 100% !important; top: 0}
Related
[
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'ONE', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ]
]
My array consists of arrays that are the same. How do I combine the ones that are the same?
Array reduce is what you would want to use to total your amounts while keeping them as key/value arrays although I might personally map them as { key: value } and then reduce for a simpler end result.
const group = [
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'ONE', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ]
];
const totals = group.reduce((accumulator, [key, value]) => {
const index = accumulator.findIndex(([k,v]) => k === key);
if (index === -1) {
return [ ...accumulator, [key, value] ];
}
const newTotal = [ key, ( accumulator[index][1] + value ) ];
return [ ...accumulator.slice(0,index), newTotal, ...accumulator.slice(index + 1) ];
},[]);
const totalsAsObject = group.reduce((accumulator, [key, value]) => {
const objectKeys = Object.keys(accumulator);
if (objectKeys.includes(key)) {
return { ...accumulator, [key]: accumulator[key] + value }
}
return { ...accumulator, [key]: value }
},
{}
);
console.log(totals);
console.log(totalsAsObject);
there you go
var a = [
["TWENTY", 20],
["TWENTY", 20],
["TWENTY", 20],
["TWENTY", 20],
["TEN", 10],
["FIVE", 5],
["ONE", 1],
["QUARTER", 0.25],
["QUARTER", 0.25],
["DIME", 0.1],
["DIME", 0.1],
["PENNY", 0.01],
["PENNY", 0.01],
["PENNY", 0.01]
];
var b = a.reduce((acc, curr) => {
if (acc[curr[0]]) acc[curr[0]] += curr[1];
else acc[curr[0]] = curr[1];
return acc;
}, {});
console.log(b);
You can use reduce to sum totals for unique index 0 in the input array:
const data = [ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'ONE', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ]
;
const result = Object.entries(data.reduce((a, e) => {
a[e[0]] = e[1] + (a[e[0]] || 0);
return a;
}, {}));
console.log(result);
You can wrap a reduce function with a map accumulator and transform the result back into an array using Array.from
result = Array.from(arr.reduce((a, cv) => {
return ([t, amt] = cv,
(a.has(t)) ? a.set(t, a.get(t) + amt) : a.set(t, amt), a)
}, new Map()));
let arr = [
['TWENTY', 20],
['TWENTY', 20],
['TWENTY', 20],
['TWENTY', 20],
['TEN', 10],
['FIVE', 5],
['ONE', 1],
['QUARTER', 0.25],
['QUARTER', 0.25],
['DIME', 0.1],
['DIME', 0.1],
['PENNY', 0.01],
['PENNY', 0.01],
['PENNY', 0.01]
],
result = Array.from(arr.reduce((a, cv) => {
return ([t, amt] = cv,
(a.has(t)) ? a.set(t, a.get(t) + amt) : a.set(t, amt), a)
}, new Map()));
console.log(result);
ES6 alternative :
const data = [ [ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TWENTY', 20 ],
[ 'TEN', 10 ],
[ 'FIVE', 5 ],
[ 'ONE', 1 ],
[ 'QUARTER', 0.25 ],
[ 'QUARTER', 0.25 ],
[ 'DIME', 0.1 ],
[ 'DIME', 0.1 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ],
[ 'PENNY', 0.01 ] ]
const result = data.reduce((o, [k, v]) => (o[k] = v + o[k] || v, o), {})
console.log( result )
console.log( Object.entries(result) )
I have this array :
[ [ 1, 'a' ], [ 2, 'b' ], [ 1, 'd' ], [ 9, 'e' ], [ 1, 'f' ], [ 11, 'g' ], [ 9, 'h' ], [ 3, 'i' ] ]
and I would like to have :
[ [ 11, 'g' ], [ 9, 'e' ], [ 9, 'h' ], [ 3, 'i' ], [ 2, 'b' ], [ 1, 'a' ], [ 1, 'd' ], [ 1, 'f' ] ]
How can I do that with javascript please ?
I tried sort(), I also tried with sort(compare) with :
function compare(x, y) {
return x - y;
}
You can use .sort() with Array Destructuring like this:
function compare([a], [b]) {
return b - a;
}
Demo:
let a = [ [ 1, 'a' ], [ 2, 'b' ], [ 1, 'd' ], [ 9, 'e' ], [ 1, 'f' ], [ 11, 'g' ], [ 9, 'h' ], [ 3, 'i' ] ];
a.sort(compare);
function compare([a], [b]) {
return b - a;
}
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In case first elements match, you can sort based on 2nd element as well:
function compare([a, c], [b, d]) {
return (b - a) || c.localeCompare(d)
}
Demo:
let a = [ [ 2, 'b' ], [ 1, 'd' ], [ 9, 'e' ], [ 1, 'f' ], [ 11, 'g' ], [ 9, 'h' ], [ 3, 'i' ], [ 1, 'a' ] ];
a.sort(compare);
function compare([a, c], [b, d]) {
return (b - a) || c.localeCompare(d);
}
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0 }
You need to compare the first element in the nested array since you want to sort based on that number.
function compare(x, y) {
return y[0] - x[0];
}
var data = [
[1, 'a'],
[2, 'b'],
[1, 'd'],
[9, 'e'],
[1, 'f'],
[11, 'g'],
[9, 'h'],
[3, 'i']
];
function compare(x, y) {
return y[0] - x[0];
}
data.sort(compare);
console.log(data);
In case you want to sort based on second element(secondary sorting in case the first element is same) then use String#localeCompare method for comparing.
function compare(x, y) {
return y[0] - x[0] || x[1].localeCompare(y[0]);
}
var data = [
[2, 'b'],
[1, 'd'],
[9, 'e'],
[1, 'f'],
[1, 'a'],
[11, 'g'],
[9, 'h'],
[3, 'i']
];
function compare(x, y) {
return (y[0] - x[0]) || x[1].localeCompare(y[1]);
}
data.sort(compare);
console.log(data);
Compare the elements based on their first element, which is the number.
var a = [ [ 1, 'a' ], [ 2, 'b' ], [ 1, 'd' ], [ 9, 'e' ], [ 1, 'f' ], [ 11, 'g' ], [ 9, 'h' ], [ 3, 'i' ] ];
a = a.sort((a,b) => {
return b[0] - a[0]
});
console.log(a)
Use sort to compare first element and if first element is same then compare the second element.
arr.sort( (a,b) => (b[0] - a[0]) || (b[1] - a[1]) )
Demo
var arr = [ [ 1, 'a' ], [ 2, 'b' ], [ 1, 'd' ], [ 9, 'e' ], [ 1, 'f' ], [ 11, 'g' ], [ 9, 'h' ], [ 3, 'i' ] ];
arr.sort( (a,b) => (b[0] - a[0]) || (b[1] - a[1]) );
console.log(arr);
I am working with javascript arrays, where i have an array of arrays like,
var arr = [
[ 73.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 3.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 73.0192222, 33.5778921 ],
[ 73.0192222, 33.5778921 ]];
There, i needed to remove the duplicate arrays. I have tried this method but it didn't worked for me, may be i am missing or doing something wrong.
var distinctArr = Array.from(new Set(arr));
Although this method works only for array of objects. If someone can help, please do help. Thanks for your time.
Lodash is great lib for doing this little things.
uniqWith with compare isEqual should resolve your problem.
var arr = [
[ 73.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 3.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 73.0191641, 33.5720131 ],
[ 73.0192222, 33.5778921 ],
[ 73.0192222, 33.5778921 ]];
_.uniqWith(arr,_.isEqual)
return -> [Array(2), Array(2), Array(2)]
You can use following approach.
var arr = [ { person: { amount: [1,1] } }, { person: { amount: [1,1] } }, { person: { amount: [2,1] } }, { person: { amount: [1,2] } }, { person: { amount: [1,2] } }];
hash = [...new Set(arr.map(v => JSON.stringify(v)))].map(v => JSON.parse(v));
document.write(`<pre>${JSON.stringify(hash, null, 2)}</pre>`);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
example we have this js array (some kind like lat, lng):
items = [
[aa,aa],
[bb,bb],
[cc,cc]
]
the result that i expected should be like this:
A = [
[aa,aa],
[bb,bb]
]
B = [
[bb,bb],
[cc,cc]
]
You are trying to iterate over two consecutive elements (arrays), you can use ruby_cons.
Note: This is a Ruby solution to iterate over consecutive elements.
items.each_cons(2) do |arr|
p arr
end
in javascript, you can try sth like,
> items
[ [ 42.32, 47.32 ], [ 49.434, 41.343 ], [ 43.34, 43.45 ] ]
> container = []
[]
> for(var i = 0; i<items.length-1; i++) {
... container.push(items.slice(i, i+2));
... }
2
> container[0]
[ [ 42.32, 47.32 ], [ 49.434, 41.343 ] ]
> container[1]
[ [ 49.434, 41.343 ], [ 43.34, 43.45 ] ]
more generalized solution, inspired from ruby's each_cons(n) enumerable method.
> each_cons = function(enm, cons_size) {
... var results = [];
... /*
... * checking numericality like typeof cons_size == 'number'
... * might be useful. but i'am skipping it.
... */
... cons_size = (cons_size < 1 ? 1 : cons_size );
... // setting default to 2 might be more reasonable
... for (var i=0; i<=enm.length - cons_size; i++) {
..... results.push(enm.slice(i, i+cons_size));
..... }
... return results;
... }
[Function: each_cons]
> x = [1,2,3,4,5,6,7,8,9,0];
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ]
> each_cons(x, 0)
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], [ 9 ], [ 0 ] ]
> each_cons(x, 1)
[ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 6 ], [ 7 ], [ 8 ], [ 9 ], [ 0 ] ]
> each_cons(x, 2)
[ [ 1, 2 ],
[ 2, 3 ],
[ 3, 4 ],
[ 4, 5 ],
[ 5, 6 ],
[ 6, 7 ],
[ 7, 8 ],
[ 8, 9 ],
[ 9, 0 ] ]
> each_cons(x, 3)
[ [ 1, 2, 3 ],
[ 2, 3, 4 ],
[ 3, 4, 5 ],
[ 4, 5, 6 ],
[ 5, 6, 7 ],
[ 6, 7, 8 ],
[ 7, 8, 9 ],
[ 8, 9, 0 ] ]
>
> x= "hippopotomonstrosesquipedaliophobia"; //https://en.wiktionary.org/wiki/hippopotomonstrosesquipedaliophobia
'hippopotomonstrosesquipedaliophobia'
> each_cons(x, 3)
[ 'hip',
'ipp',
'ppo',
'pop',
'opo',
'pot',
'oto',
'tom',
'omo',
'mon',
'ons',
'nst',
'str',
'tro',
'ros',
'ose',
'ses',
'esq',
'squ',
'qui',
'uip',
'ipe',
'ped',
'eda',
'dal',
'ali',
'lio',
'iop',
'oph',
'pho',
'hob',
'obi',
'bia' ]
>
> x = [[1,2], ['a', 'b'], [2,3,4, {a: 5}]]
[ [ 1, 2 ], [ 'a', 'b' ], [ 2, 3, 4, { a: 5 } ] ]
> each_cons(x, 2)
[ [ [ 1, 2 ], [ 'a', 'b' ] ],
[ [ 'a', 'b' ], [ 2, 3, 4, [Object] ] ] ]
I have this input array already sorted on the key:
var sortedArray = [ [ 'de', [ 1 ] ],
[ 'elle', [ 1 ] ],
[ 'elle', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'la', [ 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1 ] ],
[ 'voiture', [ 1 ] ]
];
I want to obtain this reduced Array :
[ [ 'de', [ 1 ] ],
[ 'elle', [ 1, 1 ] ],
[ 'la', [ 1, 1, 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1, 1 ] ]
];
I proceed like that :
sortedArray.forEach((elem, index, arr) => {
if (elem[0] === arr[index + 1][0]){
arr[index][1].push(1);
arr.splice(index + 1, 1);
}
});
console.log(sortedArray);
But I can't understand why I obtain this result:
[ [ 'de', [ 1 ] ],
[ 'elle', [ 1, 1 ] ],
[ 'la', [ 1, 1 ] ],
[ 'la', [ 1 ] ],
[ 'le', [ 1 ] ],
[ 'maison', [ 1 ] ],
[ 'voiture', [ 1, 1 ] ]
]
Help would be apreciated.
The issue is that you're splicing your array while iterating over it without resetting your current index. One way to get the desired result while using splice is to do something like this:
sortedArray.forEach((elem, index, arr) => {
while (arr[index + 1] && elem[0] === arr[index + 1][0]){
arr[index][1].push(1);
arr.splice(index + 1, 1);
}
});
Basically we're changing the if statement to a while loop and adding an extra check.
Use Array.prototype.reduce to create a new array. Because the original array is sorted, you only need to push 1 to the last item in the array, as long as it's the same as the current item, and add a new item whenever that's not true:
var sortedArray = [
['de', [1]],
['elle', [1]],
['elle', [1]],
['la', [1]],
['la', [1]],
['la', [1]],
['le', [1]],
['maison', [1]],
['voiture', [1]],
['voiture', [1]]
];
var result = sortedArray.reduce(function(result, item) {
if (!result.length || item[0] !== result[result.length - 1][0]) { // check if 1st results array is empty or if current item 'key' doesn't match the last item it result
result.push([item[0], []]); // push a new 'key' item with an empty array of 1s
}
result[result.length - 1][1].push(1); // push 1 to last item in result
return result;
}, []);
console.log(result);