skip to Main Content

This is regarding JavaScript. I have a response data like this which contains pairs of objects (note that the pairs can also be of 3 or 4 or any number and the pair ids are sorted). I want to alter the data such that after each matching pairs, I append one object.

[
  {
    pairId: 1,
    name: "abc",
    count: 10
  },
  {
    pairId: 1,
    name: "xyz
    count: 20
  },
  {
    pairId: 2,
    name: "abc"
    count: 15
  },
  {
    pairId: 2,
    name: "xyz,
    count: 25
  }
]

I want to achieve the data where I append one object after each matching pairs updating the count like this

[
  {
    pairId: 1,
    name: "abc",
    count: 10
  },
  {
    pairId: 1,
    name: "xyz
    count: 20
  },
  {
    pairId: 1,
    count: 30
  },
  {
    pairId: 2,
    name: "abc"
    count: 15
  },
  {
    pairId: 2,
    name: "xyz,
    count: 25
  }
  {
    pairId: 2,
    name: "mno,
    count: 5
  }
  {
    pairId: 2,
    count: 45
  }
]

Can anybody help achieve this?

While this question seems like a duplicate but I also wanted to know how to achieve pushing item to the end of last matching paired item.

3

Answers


  1. You could do this with a loop and try to juggle the current "run" of matching ids, and handle when you encounter a new id, and handle the start/end edge cases.

    But a simpler solution is to group your elements by id, and for each group, if it has more than one element, add a new element with the sum of that group’s count field.

    const items = [
      {
        pairId: 1,
        name: 'abc',
        count: 10,
      },
      {
        pairId: 1,
        name: 'xyz',
        count: 20,
      },
      {
        pairId: 2,
        name: 'abc',
        count: 15,
      },
      {
        pairId: 2,
        name: 'xyz',
        count: 25,
      },
      {
        pairId: 3,
        name: 'xyz',
        count: 25,
      },
    ];
    
    // Group the items by pairId
    const groups = items.reduce(
      (groups, item) => ({
        ...groups,
        [item.pairId]: [...(groups[item.pairId] || []), item],
      }),
      {}
    );
    
    // For each group, if has more than one element, append a new one with the sum
    // of the previous elements. Object.values() takes advantage of the facts that
    // object keys are iterated over in insertion order, so the resulting array is
    // in the same order as the original one
    const result = Object.values(groups).flatMap((group) => [
      ...group,
      ...(group.length > 1
        ? [
            {
              ...group[0],
              count: group.reduce((sum, item) => sum + item.count, 0),
            },
          ]
        : []),
    ]);
    
    console.log(result);
    
    Login or Signup to reply.
  2. let arr = [
      {
        pairId: 1,
        name: "abc",
        count: 10
      },
      {
        pairId: 1,
        name: "xyz",
        count: 20
      },
      {
        pairId: 2,
        name: "abc",
        count: 15
      },
      {
        pairId: 2,
        name: "xyz",
        count: 25
      }
    ];
    
    function append(arr){
        let new_arr = [];
        let current_id = arr[0].pairId;
        let current_sum = 0;
        //iterate arr
        for(let i = 0; i < arr.length; i++){
            //if next pair or the end
            if(current_id!=arr[i].pairId){
               //push new element
               new_arr.push({
                pairId : current_id,
                count  : current_sum,
               });
               //refresh sum and change current id
               current_id  = arr[i].pairId;
               current_sum = 0;
               i--;
            } else {
               new_arr.push(arr[i]);
               current_sum += arr[i].count;
            }
        }
        //push last
        new_arr.push({
                pairId : current_id,
                count  : current_sum,
               });
        return new_arr;
    }
    console.log(append(arr));

    something like this: it is iterate through all cycle and if the id have changed then the pair also changed and the algorithm can calculate and paste new element, also in the end of cycle pushed last element.

    Login or Signup to reply.
  3. here is a solution with manual loops and by keeping track of the previous id and the the sums. the current pairId not equal to prevPairId means a new group has started then we push the summed object to the array and reset the group sum prevSum and set the prevPairId to current pairId .
    count !== undefined check to handle edge case happening at the end of the array where data[i] is undefined. (Note the loop is running for array length + 1 times)

    const data = [  {    pairId: 1,    name: "abc",    count: 10  },  {    pairId: 1,    name: "xyz",    count: 20  },  {    pairId: 2,    name: "abc",    count: 15  },  {pairId: 2,    name: "xyz",    count: 25  },    {    pairId: 2,    name: "xyz",    count: 5  }]
    
    
    let prevPairId, prevSum = 0, newData = []
    for (let i = 0; i <= data.length; i++) {
      const { pairId, name, count } = data[i] || {}
      if (pairId !== prevPairId) {
        if (prevPairId) newData.push({ pairId: prevPairId, count: prevSum })
        prevSum = 0
        prevPairId = pairId
      }
      if (count !== undefined) {
        newData.push({ pairId, name, count })
        prevSum += count
      }
    }
    
    console.log(newData)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search