0

I have 2 array that consist object :

a = 
[
 {
  id: 105647,
  name: 'name1'
 },
 {
  id: 105941,
  name: 'name2'
 },
 {
  id: 106177,
  name: 'name3'
 }
]

b = 
[
 [
  {
   id: 105647,
   transactionDate: '2022-03-21',
   order: 1
  },
  {
   id: 105647,
   transactionDate: '2022-03-22',
   order: 2
  }
 ],
 [
  {
   id: 106177,
   transactionDate: '2022-03-24',
   order: 1
  },
 ]
]

As you can see, that in b is not always have data for each id in variable a.

And my desired output would be

a = 
[
 {
  id: 105647,
  name: 'name1',
  dataB:
   [
    {
     id: 105647,
     transactionDate: '2022-03-21',
     order: 1
    },
    {
     id: 105647,
     transactionDate: '2022-03-22',
     order: 2
    }
   ]
 },
 {
  id: 105941,
  name: 'name2'
 },
 {
  id: 106177,
  name: 'name3',
  dataB: 
   [
    {
     id: 106177,
     transactionDate: '2022-03-24',
     order: 1
    },
   ]
  }
]

the b variable should be pushed to new variable dataB inside object of array on variable a. And if no dataB exist on a it would not create dataB on a / create the dataB but with empty array.

I was already try with some

for (let i = 0; i<a.length; i++) {
  a[i]['dataB'] = b[i]
}

the result is not pushed by id, but by index. The problem is b not always have data for each id in variable a. And what i'm trying was not what i looking for.

Please ask me if you need more information if it's still not enough to solve that case.

2
  • The general process to solve problems like this is to create an object that uses the ID values as keys. Then when you loop over the other array, it's easy to find the object with the same ID. Commented Apr 15, 2022 at 15:01
  • To add on, if the values corresponding to the ID keys (from b) are arrays, then when you .map over a, things become much more easier to transform elements of a as per your target structure. Commented Apr 15, 2022 at 15:03

3 Answers 3

1

If your goal is to modify a, as opposed to creating a new array, you can use Array#forEach and Array#filter methods as follows:

const a = [ { id: 105647, name: 'name1' }, { id: 105941, name: 'name2' }, { id: 106177, name: 'name3' } ]; 
const b = [ [ { id: 105647, transactionDate: '2022-03-21', order: 1 }, { id: 105647, transactionDate: '2022-03-22', order: 2 } ], [ { id: 106177, transactionDate: '2022-03-24', order: 1 }, ] ];

a.forEach((elA,i) => {
    const others = b.filter(elB => elB.every(o => o.id === elA.id)).flat();
    a[i] = others.length ? {...elA, dataB: others} : elA;
});

console.log( a );

Since in b the items are already grouped by id, Array#find may be a better method, and will not need the use of Array#flat:

const a = [ { id: 105647, name: 'name1' }, { id: 105941, name: 'name2' }, { id: 106177, name: 'name3' } ]; 
const b = [ [ { id: 105647, transactionDate: '2022-03-21', order: 1 }, { id: 105647, transactionDate: '2022-03-22', order: 2 } ], [ { id: 106177, transactionDate: '2022-03-24', order: 1 }, ] ];

a.forEach((elA,i) => {
    const others = b.find(elB => elB.every(o => o.id === elA.id));
    a[i] = others ? {...elA, dataB: others} : elA;
    /*OR: you can replace the above one line with the following 3
    if( others ) {
        a[i].dataB = others;
    }*/
});

console.log( a );

Sign up to request clarification or add additional context in comments.

3 Comments

iwas trying using your code, but it's not working. My mistake, the b data actually contains 2 [] inside, i was updated on my post. Is your code can still work on that format data like that ? thanks
Take a look at the updated code.
thankss, it's perfectly work like i would
1

loop thought a array,

on each iteration find all matches

if array is not empty - assign it to new field dataB

    const a = 
    [
     {
      id: 105647,
      name: 'name1'
     },
     {
      id: 105941,
      name: 'name2'
     },
     {
      id: 106177,
      name: 'name3'
     }
    ]

    const b = 
[
 [
  {
   id: 105647,
   transactionDate: '2022-03-21',
   order: 1
  },
  {
   id: 105647,
   transactionDate: '2022-03-22',
   order: 2
  }
 ],
 [
  {
   id: 106177,
   transactionDate: '2022-03-24',
   order: 1
  },
 ]
];

    const result = a.map(i => {
    const foundTrancactions = b.flat().filter(el => el.id === i.id);
return {...i, ...(foundTrancactions?.length ? {dataB: foundTrancactions} : {})}
    })

    console.log(result)

UPDATE

  • have changed b array
  • added flat() for b

6 Comments

You may need to notify that a will no longer remain what it was. After console.log(result), you may do a console.log(a) to observe that it has also changed. This is because i is being mutated.
I have updated, thanks
i was using your code, but the dataB is not show
ohh my bad, the b data was different. I was updating my code above, there's double [] actually on b, how to make your code working on data like that ? thanks @shutsman
@user18605090 I have updated answer, simply need to add flat() before filter()
|
0

This solution is non-mutating and employs the idea shared by Barmar in comments above.

Code Snippet

const getTransformedArray = (orig, delta) => {
  // first, construct a key-value pair using "b" array (called "delta" here)
  const deltaMap = delta
    .flat()       // since "b" is nested, use ".flat()" to flatten it
    .reduce(
      (acc, itm) => ({
        ...acc,         // retain existing results from "acc" (accumulator)
        [itm.id]: (
          acc[itm.id] || []     // if "itm.id" already exists, keep its array
        ).concat([{...itm}])    // append the current "itm"
      }),
      {}                // "acc" is initially set to empty object "{}"
    );
  // now, iterate through "a" array (named "orig" here)
  return orig.map(
    ({id, name}) => ({    // de-structure to directly access "id", "name" props
      id, name,           // retain "id", "name"
      ...(                // add new prop "dataB" only if it's in deltaMap
        id in deltaMap
        ? { dataB: deltaMap[id] }
        : {}              // if no matching "id" in "deltaMap", don't add "dataB"
      )
    })
  );
};


const a = 
[
 {
  id: 105647,
  name: 'name1'
 },
 {
  id: 105941,
  name: 'name2'
 },
 {
  id: 106177,
  name: 'name3'
 }
]

const b = [
 [
  {
   id: 105647,
   transactionDate: '2022-03-21',
   order: 1
  },
  {
   id: 105647,
   transactionDate: '2022-03-22',
   order: 2
  }
 ],
 [
  {
   id: 106177,
   transactionDate: '2022-03-24',
   order: 1
  },
 ]
];

// invoke the transform function
console.log('transformed array: ', getTransformedArray(a, b));

// display "a" and "b" arrays to show those were not mutated
console.log('original a: ', a);
console.log('original b: ', b);
.as-console-wrapper { max-height: 100% !important; top: 0 }

Explanation

Inline comments provided in the snippet above.

2 Comments

my bad, the b data was actually has 2 [], i was updated on my post. That's why your code still not working on me. Can you provide with my updates ?
Just needed to add one ".flat()" in the method. It's updated.

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.