1

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 codes 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.

Ofir G
7646 silver badges19 bronze badges
asked Feb 14, 2018 at 12:43
2
  • Your array does not look like valid JS Commented Feb 14, 2018 at 12:50
  • What is the result that you are getting ? Are you getting anything at all ? What Debug attempts have you made so far ? Commented Feb 14, 2018 at 12:52

9 Answers 9

1

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}

jsfiddle

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" }]
*/
answered Feb 14, 2018 at 13:18
Sign up to request clarification or add additional context in comments.

Comments

0

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;
}, []);

answered Feb 14, 2018 at 12:58

3 Comments

I think this is much harder to grasp than my version
You version doesnt take into account the fact that the items in the search array might not be ordered by code
That is a simple sort. I have assumed it is
0

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"}
answered Feb 14, 2018 at 13:05

Comments

0

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);

answered Feb 14, 2018 at 12:58

Comments

0

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);

answered Feb 14, 2018 at 13:04

Comments

0

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 );

answered Feb 14, 2018 at 13:18

Comments

0

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));

answered Feb 14, 2018 at 13:54

Comments

0

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; }

answered Feb 14, 2018 at 13:26

Comments

0

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);

answered Feb 14, 2018 at 17:17

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.