Remove duplicate certain column values Javascript 2D array - javascript

I have an array for example :
var array = [
[ 1, "Hello", "red", 0, "yes"],
[ 2, "Hello", "red", 1, "no"],
[ 3, "Hello", "blue", 4, "no"],
[ 4, "Sunshine", "yellow", 5, "yes"],
[ 5, "Hello", "red", 6, "yes"],.....]
Now I want to remove array based on multiple column lets say (2,3,5):
so based on 3 column I want to remove duplicates and keep first occurrence. my result should be like:
array = [[ 1, "Hello", "red", 0, "yes"],
[ 2, "Hello", "red", 1, "no"],
[ 3, "Hello", "blue", 4, "no"],
[ 4, "Sunshine", "yellow", 5, "yes"],....]
you see hello, red & yes matched. in column 2,3,5 so the first occurrence was only kept rest was removed. now I can not figure it out how to solve this complex issue.
function pullgm() {
// ss = SpreadsheetApp.getActiveSpreadsheet()
// sh2 = ss.getSheetByName("GP")
// sh3 = ss.getSheetByName("GM")
// var lr2 = sh2.getLastRow()
// var lc2 = sh2.getLastColumn()
// var lr3 = sh3.getLastRow()
// var lc3 = sh3.getLastColumn()
var array = [
[1, 'Hello', 'red', 0, 'yes'],
[2, 'Hello', 'red', 1, 'no'],
[3, 'Hello', 'blue', 4, 'no'],
[4, 'Sunshine', 'yellow', 5, 'yes'],
[5, 'Hello', 'red', 6, 'yes'],
];
var hash = Object.create(null),
length = array.length,
result = [],
element,
i,
key,
ref;
for (i = 0; i < length; i++) {
element = array[i];
key = array[i][0] + '|' + array[i][1] + '|' + array[i][6];
ref = hash[key];
if (ref) {
continue;
}
hash[key] = element.slice();
result.push(hash[key]);
}
console.log(array);
}
pullgm();

You could take a Set with a function which builds a key of the wanted indices.
After checking the set with the combined key, add either the key and return the actual data set or discard the actual array.
const
uniqueBy = (fn, s = new Set) => o => (k => !s.has(k) && s.add(k))(fn(o)),
key = keys => o => keys.map(k => o[k]).join('|'),
data = [[1, "Hello", "red", 0, "yes"], [2, "Hello", "red", 1, "no"], [3, "Hello", "blue", 4, "no"], [4, "Sunshine", "yellow", 5, "yes"], [5, "Hello", "red", 6, "yes"]],
result = data.filter(uniqueBy(key([1, 2, 4])));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to make an array of objects out of two non symmetrical arrays?

am stuck now for the whole day and cannot get any further. I know, that I am missing a small thing, but just can't find it.
I got two arrays:
arrKeys = ["a", "b", "c"]
arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
I would like to get an array of objects, that looks like:
myObj = [
{
"a": 1,
"b": 2,
"c": 3
},
{
"a": 4,
"b": 5,
"c": 6
},
{
"a": 7,
"b": 8,
"c": 9
}
]
I tried to do something like:
const myObj = arrKeys.reduce((newObj, key, index) => {
if (arrValues[index] == undefined) arrValues[index] = null
newObj[key] = aarValues[index]
return newObj
}, {})
cosnole.log(myObj)
But the problem is, that arrKeys is looping only once and I do not know, how to "reset" the counter each time arrKeys gets to max length. Also I got only an object back, not an array of objects:
My result
myObj = {
"a": 1,
"b": 2,
"c": 3
}
Any ideas are really appreaciated.
You can iterate over the values, creating arrKeys.length chunks at a time, and then creating an object from the chunk by mapping the chunk index to the appropriate key. This approach has the advantage that if arrValues is not an exact multiple of arrKeys length, it will still work:
const f = (arrKeys, arrValues) => {
const result = []
const kLen = arrKeys.length
const vLen = arrValues.length
for (i = 0; i < vLen; i += kLen) {
chunk = arrValues.slice(i, i + kLen)
result.push(Object.fromEntries(chunk.map((v, i) => [arrKeys[i], v])))
}
return result;
}
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9]))
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
console.log(f(["a", "b", "c", "d"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
You can use modulo operator to get check for every keys.length nth element and then add a new object by slicing the values array where the start is current index and end current index + keys.length
const f = (keys, values) => values.reduce((r, e, i) => {
if (i % keys.length === 0) {
const index = i / keys.length
r[index] = values.slice(i, i + keys.length).reduce((r, e, i) => {
r[keys[i]] = e
return r
}, {})
}
return r
}, [])
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9]))
console.log(f(["a", "b", "c", 'g'], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(f(["a", "b"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
One way would be to loop through the arrValues using a conventional for...loop.
We can use the modulus operator % to determine where we are in the run of three.
Check the below for a demo:
var arrKeys = ["a", "b", "c"];
var arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9];
var myObj = [];
var newObj = null;
for(var i=0; i<arrValues.length; i++)
{
if(i % 3 === 0) // First run of three
newObj = {};
newObj[ arrKeys[i % 3] ] = arrValues[i];
if(i % 3 === 2) // We're at the end of the run of three
myObj.push(newObj);
}
console.log(myObj);
i do this with reduce
const arrKeys = ["a", "b", "c"]
const arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
let myObj = [];
arrValues.reduce((pre, cur,i) => {
pre[arrKeys[i % 3]] = cur;
if (i % 3 === 2) {
myObj.push(pre);
return {};
} else return pre;
}, {})
console.log(myObj)
you can do that...
const
arrKeys = ['a', 'b', 'c']
, arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
, myObj = arrValues.reduce((r,v,i) =>
{
if (!(i%3)) r.a.push(r.o = {})
r.o[arrKeys[i%3]] = v
return r
},{ o:null,a:[] }).a
;
console.log(myObj)
I think your desire to use Array#reduce was a good one, only I would use it:
To break the larger array into chunks of 3, then
To convert the chunks into objects
const arrKeys = ["a", "b", "c"],
arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
output = arrValues
.reduce(
(prev,cur,i,arr) =>
i % 3 === 0 ?
[
...prev,
arr.slice(i, i+3)
.reduce(
(ac,cu,j) =>
({...ac,[arrKeys[j]]:cu}), {}
)
] :
prev, []
);
console.log( output );

Sum array of arrays (matrix) vertically

How can I sum vertically all data from an array of arrays?
arrayOfArrays = [{
label: 'First Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Second Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Third Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
}
];
var result = arrayOfArrays.reduce(function(array1, array2) {
return array1.data.map(function(value, index) {
return value + array2.data[index];
}, 0);
});
console.log(result)
The output should be the vertical sum of arrays.
[3,6,9,12,15,18,21,24]
The problem is that array1 return always as undefined.
You code is almost correct but with 1 issues.
You are looping on accumulator. This will be an array of number in second iteration. Instead loop over array2 or current item.
Idea of .reduce is to have same signature for all iteration. If you do not pass default value for accumulator, first iteration will be of type Array<{ label: string, data: Array<number>}> and second iteration will be just Array<number>. So you can skip behavior for first iteration by passing default value as []. Now the calculation will break as array[n] will be undefined. For this, you can use a default value of 0.
So your calculation will look like:
value + (array1[index] || 0)
Following is a sample:
arrayOfArrays = [{
label: 'First Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Second Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Third Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
}
];
var result = arrayOfArrays.reduce(function(array1, array2) {
return array2.data.map(function(value, index) {
return value + (array1[index] || 0);
}, 0);
}, []);
console.log(result)
Use the index/key of map and add to the previous value.
const arrayOfArrays = [{label:'First Value', data:[1,2,3,4,5,6,7,8]},{label:'Second Value', data:[1,2,3,4,5,6,7,8]},{label:'Third Value', data:[1,2,3,4,5,6,7,8]}];
const res = arrayOfArrays.reduce((acc, cur) => (cur.data.map((i, k) => {acc[k] = acc[k] ? acc[k] += i : i}), acc), [])
console.log(res)
you're using reduce in a wrong way, but heres a for loop that does the same job:
arrayOfArrays = [{
label:'First Value', data:[1,2,3,4,5,6,7,8]},{
label:'Second Value', data:[1,2,3,4,5,6,7,8]},{
label:'Third Value', data:[1,2,3,4,5,6,7,8]
}];
const newArr = [];
for(let x = 0; x < arrayOfArrays[0].length; x++){
newArr.push(arrayOfArrays[0].data[x]+arrayOfArrays[1].data[x]+arrayOfArrays[2].data[x])
}
console.log(newArr); // new array
You can flatten the array by looping the array of objects and pushing the data property to a new array, then use reduce/map on the flattened data:
arrayOfArrays = [
{label:'First Value', data:[1,2,3,4,5,6,7,8]},
{label:'Second Value', data:[1,2,3,4,5,6,7,8]},
{label:'Third Value', data:[1,2,3,4,5,6,7,8]}
];
var data = [];
arrayOfArrays.forEach((element)=> {
data.push(element.data)
})
var sum = (r, a) => r.map((b, i) => a[i] + b);
var result = data.reduce(sum);
console.log(result);
Which outputs:
[3, 6, 9, 12, 15, 18, 21, 24]
Working fiddle
If you know that the length of each array is same. you can do as follows
arrayOfArrays = [{
label: 'First Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Second Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Third Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
}
];
let out = arrayOfArrays.reduce((acc, {data}) => acc.map((e, i) => e+data[i]), new Array(8).fill(0));
console.log(out)
You are passing the wrong accumulator which should be an array also in wrong place, it must be with reduce not with map
var result = arrayOfArrays.reduce(function (array1, array2) {
return array1.map(function (value, index) {
return value + array2.data[index];
});
}, Array(8).fill(0));
I would do it like this:
Introduce a helper transport function:
const transport = (arr) => arr[0].map((col, i) => arr.map(row => row[i]));
Get a proper matrix:
const matrix = arrayOfArrays.map(el => el.data)
Then the task becomes trivial:
const res = transport(matrix).map(arr => arr.reduce((x, y) => x + y))
// > (8) [3, 6, 9, 12, 15, 18, 21, 24]
You could take advantage of function generators in case you need to later transform or alterate the values, or just iterate them without needing the entire result set.
In this solution, a function generator is used and the logic applied is:
Get the array with the longest length (assuming length might change)
Get all the elements at index i from 0 to longest length and yield their sum.
arrayOfArrays = [{
label: 'First Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Second Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
},
{
label: 'Third Value',
data: [1, 2, 3, 4, 5, 6, 7, 8]
}
];
/**
Sums elements of arrays inside the array vertically.
*/
function* sumVertically(arr) {
// Get the longest array.
const longestArrayLength = arr.sort(({length: l1}, {length: l2}) => l1 - l2)[0].length;
// Acquire all elements at index [i] of each array and sum them. Yield the sum.
for (let i = 0; i < longestArrayLength; i++) yield arr.map(e => e[i]).reduce((a,b) => a + b, 0);
}
const result = [...sumVertically(arrayOfArrays.map(i => i.data))];
console.log(result);

using array as key to loop through objects in JavaScript

I am learning JavaScript and have spent a good deal of time practicing looping through arrays and arrays of Objects. I wanted to learn how to use an array as a filter on an array of Objects. I couldn't find any articles that explained how to do this, so I had a go myself using a nested loop. However, I cannot get it to work.
Var catKey[]; is the array holding the data I want to use to filter through var posts[]; , identify which objects have a match in the Property cat: [] and return the title properties. I know I could use array.Filter but I want to be able to do this on the assumption I wont always know the number of items in the catKey array. The use case would be for a situation where I use an event handler that when a link I add is clicked on a Post in WordPress and returns the category Ids, I would then search through the list of Posts to find others that have the same category Ids. Can anyone tell me where I am going wrong.
var catKey = [2, 6];
var posts = [
{
id: 1,
cat: [1, 2, 3],
title: "Hello World"
},
{
id: 2,
cat: [5, 6, 7],
title: "Hello JavaScript"
},
{
id: 3,
cat: [8, 9],
title: "Hello Arrays!"
}
];
for (var i = 0; i < catKey.length; i++) {
for (var j = 0; j < posts.length[i]; j++) {
if (catKey[i] === posts[j].cat) {
document.write(posts[j].title);
}
}
}
To find the first entry to match your conditions you can make use of Array.prototype.find() function:
var catKey = [2, 6];
var posts = [
{ id: 1, cat: [1, 2, 3], title: "Hello World" },
{ id: 2, cat: [5, 6, 7], title: "Hello JavaScript" },
{ id: 3, cat: [8, 9], title: "Hello Arrays!" }
];
const resObj = posts
.find(p => p.cat.some(c => catKey.includes(c)))
.title;
console.log(resObj)
Or to find all, use Array.prototype.filter():
var catKey = [2, 6];
var posts = [
{ id: 1, cat: [1, 2, 3], title: "Hello World" },
{ id: 2, cat: [5, 6, 7], title: "Hello JavaScript" },
{ id: 3, cat: [8, 9], title: "Hello Arrays!" }
];
const resObjs = posts
.filter(p => p.cat.some(c => catKey.includes(c)))
.map(o => o.title);
resObjs.forEach((t) => console.log(t));
Based on your question, I assume catKey contains a whitelist of numbers that the nested cat array should match, i.e. as long as any value in the cat array is found in catKeys, you want to keep them.
In that case, you can simply use .filter() to iterate through all the posts, and evaluate if there is any intersection between the individual post's cat array against the whitelist:
var filteredPosts = posts.filter(function(post) {
return post.cat.filter(function(c) { return catKey.indexOf(c) !== -1; }).length;
});
If you want to try and write in ES6, that's also not a problem: and it's even more concise!
const filteredPosts = posts.filter(post => post.cat.filter(c => catKey.includes(c)).length);
See proof-of-concept below:
var catKey = [2, 6];
var posts = [{
id: 1,
cat: [1, 2, 3],
title: "Hello World"
},
{
id: 2,
cat: [5, 6, 7],
title: "Hello JavaScript"
},
{
id: 3,
cat: [8, 9],
title: "Hello Arrays!"
}
];
var filteredPosts = posts.filter(function(post) {
return post.cat.filter(function(c) { return catKey.indexOf(c) !== -1; }).length;
});
console.log(filteredPosts);
You can use map and find together to check the values in the array with the values in the array of objects. Using map the catKey array is iterated and for every element find is used to find that element in the array inside the object inside the array named post using the .includes() method.
var catKey = [2, 6];
var posts = [{
id: 1,
cat: [1, 2, 3],
title: "Hello World"
},
{
id: 2,
cat: [5, 6, 7],
title: "Hello JavaScript"
},
{
id: 3,
cat: [8, 9],
title: "Hello Arrays!"
}];
console.log(catKey.map((e) => posts.find((x) => x.cat.includes(e))))
var catKey = [2, 6];
var posts = [
{
id: 1,
cat: [1, 2, 3],
title: "Hello World"
},
{
id: 2,
cat: [5, 6, 7],
title: "Hello JavaScript"
},
{
id: 3,
cat: [8, 9],
title: "Hello Arrays!"
}
];
var result = posts.filter(({cat})=>{
return catKey.filter((key)=>{
return cat.includes(key)
}).length > 0
})
console.log(result);
short version
posts.filter(({ cat }) => catKey.filter(key => cat.includes(key)).length > 0);

Convert an Array of Array to Array of Object [closed]

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 4 years ago.
Improve this question
I have an array of arrays (2d array), and I want to convert it into an array of objects. In the resulting array, I would like each object to have a key-name (see expected output below)
data = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 3, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
My expected result:
expected_result = [
{name: 'Apple', price: 40, quantity: 2, color: 'Red'},
{name: 'Orange', price: 35, quantity: 4, color: 'Yellow'},
{name: 'Banana', price: 25, quantity: 4, color: 'Green'},
{name: 'Pears', price: 58, quantity: 1, color: 'Violet'},
{name: 'Peach', price: 84, quantity: 2, color: 'Blue'}
];
Note The iteration of each array (in data) should be consecutive so that it gives the expected result
Seems to be there is one item extra in the quantity values. I have updated
[2, 4, 4, 3, 1, 2] to [2, 4, 4, 1, 2] removed 3 to match the result, hoping its a typo.
let data = [
["Apple", "Orange", "Banana", "Pears", "Peach"],
[40, 35, 25, 58, 84],
[2, 4, 4, 1, 2],
["Red", "Yellow", "Green", "Violet", "Blue"]
];
let output = [];
let props = ["name", "price", "quantity", "color"];
function updateInfo(row, prop){
row.filter((value, index) => {
if (output[index]) {
output[index][prop] = value;
} else {
output.push({
[prop]: value
});
}
});
};
data.filter((row, index) => {
updateInfo(row, props[index]);
});
console.log(output);
One solution consist of creating first a Map between the outter-array indexes and the property (or key) name you want to assign to them (however this could be replaced by an array like this ["name","price","quantity","color"]). Also, you can obtain the minimun length of the inner arrays to later check for non-creation of objects that won't have all the properties. After you do this pre-initialization, you can use Array.reduce() to generate your expected result:
const data = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 3, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
let mapIdxToProp = new Map([[0, "name"],[1, "price"],[2, "quantity"],[3, "color"]]);
let minLen = Math.min(...data.map(x => x.length));
let res = data.reduce((acc, arr, idx) =>
{
arr.forEach((x, j) =>
{
(j < minLen) && (acc[j] = acc[j] || {}, acc[j][mapIdxToProp.get(idx)] = x);
});
return acc;
}, []);
console.log(res);
The simplest (not most efficient) solution in my opinion is to simply loop through the array, adding to another array as you go.
let arr = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
let keys = ["name", "price", "quantity", "color"];
let output = [];
//Add's blank objects too the output array
for (let i = 0; i < arr[0].length; i++) {
output.push({});
}
//Loops through the array
for (let i = 0; i < arr.length; i++) {
//Loops through the sub array
for (let x = 0; x < arr[i].length; x++) {
//Adds the sub array to the key that corresponds to it
output[x][keys[i]] = arr[i][x];
}
}
console.log(output);

javascript several corresponding array reducing/sumup

What is the cleanest way to reduce those array ?
data = {
id: [1, 1, 1, 3, 3, 4, 5, 5, 5, ...]
v: [10,10,10, 5, 10 ...]
}
For each id there is a v corresponding. What I want is sum up v for each id. In this example the result should be
data = {
id: [1, 3, 4, 5, ...]
v: [30, 15, ...]
}
I would go for the Array.prototype.reduce() ,simple and elegant solution
var ids = [1, 1, 1, 3, 3, 3, 3, 4, 5, 6, 6, 6],
v = [10, 10, 10, 5, 10, 10, 10, 404, 505, 600, 60, 6],
data = {};
data.v = [];
data.ids = ids.reduce(function(a, b, index) {
if (a.indexOf(b) < 0) a.push(b);
if (!data.v[a.indexOf(b)]) data.v[a.indexOf(b)] = 0;
data.v[a.indexOf(b)] += v[index];
return a;
}, []);
https://jsfiddle.net/2ssbngLr/
One way of doing this, given two arrays of equal length would be to map/reduce them:
const ids = [1, 1, 1, 3, 3];
const vs = [10,10,10,5,10];
const reduced = ids
.map((val, i) => ({ id: val, value: vs[i] }))
.reduce((agg, next) => {
agg[next.id] = (agg[next.id] || 0) + next.value;
return agg;
}, {});
console.log(reduced);
// Object {1: 30, 3: 15}
Working example: https://jsfiddle.net/h1o5rker/1/
I think it can be accomplished with reduce
var data = {
id: [1, 1, 1, 3, 3],
v: [10, 10, 10, 5, 10]
}
var sumsObjs = data.v.reduce(function(sum, val, index) {
var id = data.id[index];
if (sum[id] !== undefined) {
sum[id] = sum[id] + val;
} else {
sum[id] = val;
}
return sum;
}, {});
console.log(sumsObjs);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
var data={
id: [1,1,1,10,123,4531],
v:[123,123,53,223,11,11,11]
},
_v = data.v, vinit;
document.write(data.v+'<br>');
for(var i=0;i<_v.length;i++){
vinit = _v[i];
for(var j=i+1; j<=_v.length;j++){
if(_v[j]===vinit){
delete _v[j];
}
}
};
document.write(data.v);
var data={
id: [1,1,1,10,123,4531],
v:[123,123,53,223,11,11,11,...]
},
_v = data.v, vinit;
for(var i=0;i<_v.length;i++){
vinit = _v[i];
for(var j=i+1; j<=_v.length;j++){
if(_v[j]===vinit){
delete _v[j];
}
}
}
the above code is just for the v but you can simultaneously reduce the repeating elements for id too by introducing some more variables
in the snippet you can see that there are the extra commas in the second line which shows that those elements were deleted
If the ids are always in order, a simple for loop can solve it. There is no need to get overly complicated.
data = {
id: [1, 1, 1, 3, 3, 4, 5, 5, 5],
v: [10, 10, 10, 5, 10, 1, 2, 3, 4]
};
var result = {
id: [],
v: []
};
(function() {
var ids = data.id,
vals = data.v,
lastId = ids[0],
runningTotal = vals[0];
for (var i = 1; i < ids.length; i++) {
if (lastId === ids[i]) {
runningTotal += vals[i];
}
if (lastId !== ids[i] || i + 1 === ids.length) {
result.id.push(lastId);
result.v.push(runningTotal);
lastId = ids[i];
runningTotal = vals[i];
}
}
}());
console.log(result);
Some people have posted some good solutions so far, but I haven't really seen one that does exactly what you're looking for. Here is one that takes your specific object and returns an object of the same format, but meeting your requirements and reduced.
// Your data object
data = {
id: [1, 1, 1, 3, 3],
v: [10,10,10, 5, 10]
}
// Assuming obj consists of `id` and `v`
function reduce(obj){
// We create our reduced object
var reducedObj = {
id: [],
v: []
}
// Next we create a hash map to store keys and values
var map = {};
for(var i=0; i<obj.id.length; ++i){
// If this key doesn't exist, create it and give it a value
if(typeof map[parseInt(obj.id[i])] === 'undefined'){
map[parseInt(obj.id[i])] = 0;
}
// Sum all of the values together for each key
map[parseInt(obj.id[i])] += parseInt(obj.v[i]);
}
// Now we map back our hashmap to our reduced object
for(var ele in map){
reducedObj.id.push(ele);
reducedObj.v.push(map[ele]);
}
// Return our new reduced object
return reducedObj;
}
var myReducedObject = reduce(data);
console.log(myReducedObject);
Working Fiddle
This is a solution for ordered id with Array.prototype.reduce().
var data = {
id: [1, 1, 1, 3, 3, 4, 5, 5, 5],
v: [10, 10, 10, 5, 10, 7, 8, 10, 13]
},
result = { id: [], v: [] };
data.id.reduce(function (r, a, i) {
if (r === a) {
result.v[result.v.length - 1] += data.v[i];
} else {
result.id.push(a);
result.v.push(data.v[i]);
}
return a;
}, -1);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Or a in situ version
var data = {
id: [1, 1, 1, 3, 3, 4, 5, 5, 5],
v: [10, 10, 10, 5, 10, 7, 8, 10, 13]
};
void function (d) {
var i = 1;
while (i < d.id.length) {
if (d.id[i - 1] === d.id[i]) {
d.id.splice(i, 1);
d.v[i - 1] += d.v.splice(i, 1)[0];
continue;
}
i++;
}
}(data);
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');

Categories

Resources