Reputation: 1276
I have an array like below:
var search = [
{ code: "t1", name1: "n1", name2: "n2" },
{ code: "t1", name1: "n5", name2: "n6" },
{ code: "t2", name1: "n10", name2: "n11" },
{ code: "t2", name1: "n18", name2: "n20" },
{ code: "t3", name1: "n18", name2: "n20" },
];
I want to transform this array to the format below:
var finald = [
{ code: "t1", name1: "n1,n5", name2: "n2,n6" },
{ code: "t2", name1: "n10,n18", name2: "11,n20" },
{ code: "t3", name1: "n18", name2: "n20" },
];
I have tried this as below code. but no success.
First I gathered all unique code
s from the array:
var flags = [];
var codes = [];
for(var z=0; z<search.length; z++){
if( flags[data[z].code]) continue;
flags[data[z].code] = true;
codes.push(data[z].code);
}
var finald = [];
for(var i=0; i<search.length; i++){
var name1 = [];
var name2 = [];
for(var y=0; y<codes.length; y++){
if(codes[y] == search[i].code ){
var row = {
code: codes[y],
name1:search[i].name1,
name2:search[i].name2,
};
finald.push(row);
}
}
}
Please Help.
Upvotes: 1
Views: 441
Reputation: 22534
You can use array#reduce
to group your array based on code
and push same values in an array. Get all the values using Object.values()
and then using array#map
convert the array into a string using array#join()
.
var search = [{ code: "t1", name1: "n1", name2: "n2" },{ code: "t1", name1: "n5", name2: "n6" },{ code: "t2", name1: "n10", name2: "n11" },{ code: "t2", name1: "n18", name2: "n20" },{ code: "t3", name1: "n18", name2: "n20" }],
result = Object.values(search.reduce((r,{code,name1, name2}) => {
r[code] = r[code] || {code, name1: [], name2: []};
r[code].name1.push(name1);
r[code].name2.push(name2);
return r;
},{}))
.map(({code,name1,name2}) => ({code, name1: name1.join(','), name2: name2.join(',')}));
console.log(result);
Upvotes: 0
Reputation: 754
it's not exactly what you asked for, but still try this approach.
you basically want to do a 'join' action on the array by the key 'code', so maybe try to convert your array to a map
object - key: code , value : {name1, name2}
var search = [
{code:"t1", name1:"n1", name2:"n2"},
{code:"t1", name1:"n5", name2:"n6"},
{code:"t2", name1:"n10", name2:"n11"},
{code:"t2", name1:"n18", name2:"n20"},
{code:"t3", name1:"n18", name2:"n20"}];
const myMap = new Map();
search.forEach((obj) => {
const key = obj.code;
if(!myMap.has(key)) {
myMap.set(key, {
'name1' : obj.name1,
'name2' : obj.name2
});
} else {
var ele = myMap.get(key);
ele.name1 = `${ele.name1},${obj.name1}`;
ele.name2 = `${ele.name2},${obj.name2}`;
}
});
console.log(myMap);
/*
key: "t1" => value: {name1:"n1,n5", name2:"n2,n6"},
key: "t2" => value: {name1:"n10,n18", name2:"n11,n20"},
key: "t3" => value: {name1:"n18", name2:"n20"}
*/
if you must have it in an array form add this to the above, jsfiddle
var resArray = [];
myMap.forEach((value, key) => {
resArray.push(Object.assign({'code': key}, value));
});
console.log(resArray);
/*
[{ code: "t1", name1: "n1,n5", name2: "n2,n6" },
{ code: "t2", name1: "n10,n18", name2: "11,n20" },
{ code: "t3", name1: "n18", name2: "n20" }]
*/
Upvotes: 1
Reputation: 7916
Another take to fix the problem - this code emphasizes on immutability of data, returning new objects from all iterations. This might prevent hard to find bugs when performing such operations:
var finald = transform([
{ code: "t1", name1: "n1", name2: "n2" },
{ code: "t1", name1: "n5", name2: "n6" },
{ code: "t2", name1: "n10", name2: "n11" },
{ code: "t2", name1: "n18", name2: "n20" },
{ code: "t3", name1: "n18", name2: "n20" },
]);
console.log(finald);
function transform(source) {
const keyedByCode = source.reduce((acc, item) => {
const { name1 = [], name2 = [] } = acc[item.code] || {};
return Object.assign({}, acc, {
[item.code]: {
name1: [item.name1, ...name1],
name2: [item.name2, ...name2],
},
});
}, {});
return Object.keys(keyedByCode).map((code) => ({
code,
name1: keyedByCode[code].name1.sort().join(','),
name2: keyedByCode[code].name2.sort().join(','),
}));
}
.as-console-wrapper { max-height: 100% !important; }
Upvotes: 0
Reputation: 537
The order of codes doesn't matter here:
const search = [{code:"t1", name1:"n1", name2:"n2"},
{code:"t1", name1:"n5", name2:"n6"},
{code:"t2", name1:"n10", name2:"n11"},
{code:"t2", name1:"n18", name2:"n20"},
{code:"t3", name1:"n18", name2:"n20"}];
function combineObjectsByCode(objects) {
let codes = new Set();
objects.forEach(object => codes.add(object.code));
let combinedObjects = [];
codes.forEach(code => {
let objectsWithSameCode = objects.filter(object => object.code === code);
let combinedObject;
objectsWithSameCode.forEach( obj => {
if (!combinedObject) {
combinedObject = obj;
}
else {
combinedObject.name1 = combinedObject.name1 + ', ' + obj.name1;
combinedObject.name2 = combinedObject.name2 + ', ' + obj.name2;
}
})
combinedObjects.push(combinedObject);
});
return combinedObjects;
}
console.log(combineObjectsByCode(search));
Upvotes: 0
Reputation: 26844
You can use reduce
and map
let search = [{code:"t1", name1:"n1", name2:"n2"},{code:"t1", name1:"n5", name2:"n6"},{code:"t2", name1:"n10", name2:"n11"},{code:"t2", name1:"n18", name2:"n20"},{code:"t3", name1:"n18", name2:"n20"},];
let result = Object.values( search.reduce( (c,v) => {
c[ v.code ] ? c[ v.code ].push( v ) : c[ v.code ] =[ v ];
return c;
},{}) ).map( v => {
let n1 = [], n2 = [];
v.forEach( e => { n1.push( e.name1 ); n2.push( e.name2 ); });
return { code : v[0].code, name1 : n1.join(","), name2 : n2.join(",") }
});
console.log( result );
Upvotes: 0
Reputation: 30739
You can create your own custom logic for this:
var search = [
{ code: "t1", name1: "n1", name2: "n2" },
{ code: "t1", name1: "n5", name2: "n6" },
{ code: "t2", name1: "n10", name2: "n11" },
{ code: "t2", name1: "n18", name2: "n20" },
{ code: "t3", name1: "n18", name2: "n20" },
];
//this is the result array
var result = [];
//this is a flag
var itemExist = false;
search.forEach((item) => {
//reset flag to false
itemExist = false;
//check if the object already exist in the result array or not
for(var i=0; i<result.length; i++){
//if the object exist then merge the values of name1 and name2
if(result[i].code === item.code){
result[i].name1 = result[i].name1 +','+item.name1;
result[i].name2 = result[i].name2 +','+item.name2;
itemExist = true;
//break the for loop
break;
}
}
//if object do not exist in the result array then push it
if(!itemExist){
result.push(item);
}
});
console.log(result);
Upvotes: 0
Reputation: 177975
Something like this?
You could use reduce or map but this is more understandable in my opinion for a simple task
I am assuming the search is ordered by code.
var search = [
{code:"t1", name1:"n1", name2:"n2"},
{code:"t1", name1:"n5", name2:"n6"},
{code:"t2", name1:"n10", name2:"n11"},
{code:"t2", name1:"n18", name2:"n20"},
{code:"t3", name1:"n18", name2:"n20"}
],
finald = [];
finald.push(search[0]);
for (var i = 1; i < search.length; i++) {
var f = finald[finald.length - 1];
if (f.code == search[i].code) {
f.name1 += ","+search[i].name1;
f.name2 += ","+search[i].name2;
} else {
finald.push(search[i]);
}
}
console.log(finald);
Upvotes: 0
Reputation: 413
I wrote this function:
function normalize(arr) {
var output = [];
for(var i = 0; i < arr.length; i++) {
var codeIndex = _findIndex(output, arr[i].code);
if(codeIndex !== -1) {
// Code already in output array, merge names.
output[_findIndex(output, arr[i].code)].name1 += ', ' + arr[i].name1;
output[_findIndex(arr[i].code)].name2 += ', ' + arr[i].name2;
}
else {
// Code new to output array, pus into.
output.push(arr[i]);
}
}
return output;
//
// Privates
//
function _findIndex(arr, code){
var index = -1;
for(var i = 0; i < arr.length; i++){
if(arr[i].code == code) {
index = i;
break;
}
}
return index;
}
}
Output:
0 : {code: "t1", name1: "n1, n5", name2: "n2, n6, n20"}
1 : {code: "t2", name1: "n10, n18", name2: "n11"}
2 : {code: "t3", name1: "n18", name2: "n20"}
Upvotes: 0
Reputation: 96
This should do what you want:
var search = [
{ code: "t1", name1: "n1", name2: "n2" },
{ code: "t1", name1: "n5", name2: "n6" },
{ code: "t2", name1: "n10", name2: "n11" },
{ code: "t2", name1: "n18", name2: "n20" },
{ code: "t3", name1: "n18", name2: "n20" }
];
const items = search.reduce((acc, item) => {
const code = item.code;
if (!acc[code]) acc[code] = {name1: [], name2: []};
acc[code].name1.push(item.name1);
acc[code].name2.push(item.name2);
return acc;
}, {});
const finald = Object.keys(items).reduce((acc, key) => {
const item = items[key];
acc.push({
code: key,
name1: item.name1.join(','),
name2: item.name2.join(',')
});
return acc;
}, []);
Upvotes: 0