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.

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

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

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

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

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

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

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

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

Comments

Your Answer

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.