0

I need to take two arrays of separate arrays of objects and map it to a new array of objects. I just can't seem to figure it out in ES6. I know I need to map through the first array and reduce on the second array but I am getting lost. I included a snippet, which fails on the reduce at Combined: acc[i].Combined.push(name.SId),

two arrays:

Array 1

[
    {
      "BId": 1,
      "Name": "Test1",
    },
    {
      "BId": 2,
      "Name": "Test2",
    }
]

Array 2

[
    {
      "Id": 1,
      "BId": 1,
      "SId": 2,
      "GId": 1
    },
    {
      "Id": 2,
      "BId": 1,
      "SId": 2,
      "GId": 2
    },
    {
      "Id": 3,
      "BId": 1,
      "SId": 3,
      "GId": 1
    },
    {
      "Id": 1,
      "BId": 2,
      "SId": 2,
      "GId": 1
    },
    {
      "Id": 2,
      "BId": 2,
      "SId": 2,
      "GId": 2
    },
    {
      "Id": 3,
      "BId": 2,
      "SId": 3,
      "GId": 1
    },
    {
      "Id": 3,
      "BId": 2,
      "SId": 3,
      "GId": 4
    },
]

result:

[
    {
      "BId": 1,
      "Name": Test1,
      "Combined": [{SId:2, GIds[1,2]}, {SId:3, GIds[1]}]
    }
    {
      "BId": 2,
      "Name": Test2,
      "Combined": [{SId:2, GIds[1,2]}, {SId:3, GIds[1,4]}]
    }
]

const array1 = [
        {"BId": 1,
          "Name": "Test1",
        },
        {
          "BId": 2,
          "Name": "Test2",
        }
    ];
    
const array2 = [
        {
          "Id": 1,
          "BId": 1,
          "SId": 2,
		  "GId": 1
        },
        {
          "Id": 2,
          "BId": 1,
          "SId": 2,
		  "GId": 2
        },
        {
          "Id": 3,
          "BId": 1,
          "SId": 3,
		  "GId": 1
        },
		{
          "Id": 1,
          "BId": 2,
          "SId": 2,
		  "GId": 1
        },
        {
          "Id": 2,
          "BId": 2,
          "SId": 2,
		  "GId": 2
        },
        {
          "Id": 3,
          "BId": 2,
          "SId": 3,
		  "GId": 1
        },
        {
          "Id": 3,
          "BId": 2,
          "SId": 3,
		  "GId": 4
        },
    ];
    
    
     const all = array1.map(a1 => {
      combined = array2
        .filter(a2 => a2.BId === a1.BId)
        .reduce((acc, name, i) => {

          const obj = {
            BId: name.BId,
            Name: name.Name,
            Combined: acc[i].Combined.push(name.SId),
          };
          acc.push(obj);

          return acc;
        }, []);
      return bv;
    });

3 Answers 3

1

Hope it helps...

const array1 = [
        {"BId": 1,
          "Name": "Test1",
        },
        {
          "BId": 2,
          "Name": "Test2",
        }
    ];
    
const array2 = [
        {
          "Id": 1,
          "BId": 1,
          "SId": 2,
		  "GId": 1
        },
        {
          "Id": 2,
          "BId": 1,
          "SId": 2,
		  "GId": 2
        },
        {
          "Id": 3,
          "BId": 1,
          "SId": 3,
		  "GId": 1
        },
		{
          "Id": 1,
          "BId": 2,
          "SId": 2,
		  "GId": 1
        },
        {
          "Id": 2,
          "BId": 2,
          "SId": 2,
		  "GId": 2
        },
        {
          "Id": 3,
          "BId": 2,
          "SId": 3,
		  "GId": 1
        },
        {
          "Id": 3,
          "BId": 2,
          "SId": 3,
		  "GId": 4
        },
    ];
            
const all = array1.map(arr => {
  let combined = []
  array2
  .filter(e => arr.BId === e.BId)
  .forEach(e => {
    const {GId, SId} = e
    combined.push({GId, SId})
  })
  combined = combined.reduce((acc, cur) => {
  const {GId, SId} = cur
  const idx = acc.findIndex(e => e.SId === SId)
  if (idx !== -1) {acc[idx].GId.push(GId)}
  else {acc.push({SId, GId: [GId]})}
  return acc
  },[])
  return {...arr, combined}
 });
 
 console.log(all)

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

6 Comments

Thanks for the quick response, but the result is not combined how it was stated, this is a lot closer than I got tho! GIds need to be combined within the combined object as well (thats the tricky part)
Ok, do I understand correctly that you want to aggregate based on SIds?
exactly, they group on SIds! :)
sweet. I am going to see if I can clean that up into ES6, but thats an aswer. Cheers mate.
@Harleyz You can't get more ES6 than this :D
|
1

let a_array = [
    {
      "BId": 1,
      "Name": "Test1",
    },
    {
      "BId": 2,
      "Name": "Test2",
    }
];

let b_array = [
    {
      "Id": 1,
      "BId": 1,
      "SId": 2,
      "GId": 1
    },
    {
      "Id": 2,
      "BId": 1,
      "SId": 2,
      "GId": 2
    },
    {
      "Id": 3,
      "BId": 1,
      "SId": 3,
      "GId": 1
    },
    {
      "Id": 1,
      "BId": 2,
      "SId": 2,
      "GId": 1
    },
    {
      "Id": 2,
      "BId": 2,
      "SId": 2,
      "GId": 2
    },
    {
      "Id": 3,
      "BId": 2,
      "SId": 3,
      "GId": 1
    },
    {
      "Id": 3,
      "BId": 2,
      "SId": 3,
      "GId": 4
    },
];

a_array.map( (a_object) => {
 if(!a_object.Combined) a_object.Combined = [];

 return b_array.map((b_object) => {

  if(a_object.BId === b_object.BId) {

   let c = a_object.Combined.filter( (_c) => ( _c.SId === b_object.SId ) );

   if(c && c[0]) {
    if(!c[0].GIds.includes(b_object.GId)) c[0].GIds.push(b_object.GId);

   } else {
    a_object.Combined.push({"SId": b_object.SId, "GIds": [b_object.GId]})

   }

   return a_object;

  }

 })

} )

console.log(a_array);

2 Comments

This feels like a bizarre use of map. Using map to update a value is strange enough, but using it to occasionally update it (depending upon some criteria) seems scary!
@ScottSauyet - i think filter would be okay here in place of the if(a_object.BId === b_object.BId). I will include the final result probably by end of day.
1

I might write something like this:

const combine = (arr1, arr2) => arr1 .map (({BId, ...rest}) => ({
  BId, 
  ...rest,
  Combined: Object .entries (
      arr2 .filter (({BId: b}) => b == BId)
           .map (({SId, GId}) => ({SId, GId}))
           .reduce ((a, {SId, GId}) => ({...a, [SId]: [...(a [SId] || []), GId]}), {})
  ) .map (([sid, GIds]) => ({SId: Number (sid), GIds}))
}))


const arr1 = [{BId: 1, Name: "Test1"}, {BId: 2, Name: "Test2"}]
const arr2 = [{Id: 1, BId: 1, SId: 2, GId: 1}, {Id: 2, BId: 1, SId: 2, GId: 2}, {Id: 3, BId: 1, SId: 3, GId: 1}, {Id: 1, BId: 2, SId: 2, GId: 1}, {Id: 2, BId: 2, SId: 2, GId: 2}, {Id: 3, BId: 2, SId: 3, GId: 1}, {Id: 3, BId: 2, SId: 3, GId: 4}]


console .log (combine (arr1, arr2))
.as-console-wrapper {min-height: 100% !important; top: 0}

I think it's fairly straightforward. The BId and Name properties are taken from the first array (using ...rest to include other properties if they are there.) And we calculate Combined like this:

  • The filter line finds the matching entries.

  • The first map line extracts the two properties we care about.

  • The reduce line groups them into a structure like {"2": [1, 2], "3": [1]}.

  • We call Object.entries on that to get back [["2", [1, 2]], ["3", [1]]].

  • And then the second map line turns that into [{SId: 2, GIds: [1, 2]}, {SId: 3, GIds: [1]}). Because we used the SId as a key, it was turned into a String. We use Number here to convert it back.

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.