1

I have an array of objects (old_array) that needs to be merged to become (new_array)

old_array = [
        { id: 'ffff55', name: 'f5', card: 'a', request: { device: 0, bus: 1, ship: 21 } },
        { id: 'vvvv44', name: 'v4', card: 'c', request: { device: 3, bus: 10, ship: 2 } },
        { id: 'cccc33', name: 'c3', card: 'a', request: { device: 0, bus: 1, ship: 2 } },
        { id: 'ffff55', name: 'f5', card: 'b', request: { device: 32, bus: 31, ship: 32 } },
        { id: 'cccc33', name: 'c3', card: 'e', request: { device: 21, bus: 21, ship: 22 } },
        { id: 'cccc33', name: 'c3', card: 'd', request: { device: 4, bus: 1, ship: 2 } },
        { id: 'vvvv44', name: 'v4', card: 'c', request: { device: 13, bus: 11, ship: 12 } }
    ];

new_array = [
        { id: 'ffff55', name: 'f5', unique_cards: 2, request: { device: 32, bus: 32, ship: 53 } },
        { id: 'vvvv44', name: 'v4', unique_cards: 1, request: { device: 16, bus: 21, ship: 14 } },
        { id: 'cccc33', name: 'c3', unique_cards: 3, request: { device: 25, bus: 23, ship: 26 } }
    ];
  • merge the objects with same id and name to a single object
  • merge the nested request object (Sum of its values)
  • map card to the number of unique cards (by id)

I've been trying for 4 days straight but this array manipulation was hard

My best attempt was trying to group the array of objects by id but it become more complex with many redundant values

groupByArray(xs, key) {
        return xs.reduce(function(rv, x) {
            let v = key instanceof Function ? key(x) : x[key];
            let el = rv.find((r) => r && r.key === v);
            if (el) {
                el.values.push(x);
            } else {
                rv.push({ key: v, values: [ x ] });
            }
            return rv;
        }, []);
    }

groupByArray(old_array , 'id')
7
  • 1
    show your best attempt in js Commented Mar 9, 2019 at 0:10
  • @zerkms i tried to group the arrays by id then mapping and reducing but it become more complex (more nested objects ) Commented Mar 9, 2019 at 0:14
  • You have enumerated 3 different task. Try solve only the first one and publish your best attempt. That really is an EXTREMELY FREQUENT request here: at least make a research. Commented Mar 9, 2019 at 0:16
  • @zerkms i only ask if i'm very desperate . most of what i found about merging is either a simple array or using underscore.js loddah and other stuff. 14h straight today of searching Commented Mar 9, 2019 at 0:26
  • "is either a simple array" --- you have a simple array of simple objects. The problem here is that now you have an answer, yet you still are not able to solve such sort of tasks. You indeed can copy-paste it, but tomorrow you'll be stuck again when the conditions slightly change 🤷 Commented Mar 9, 2019 at 0:27

1 Answer 1

1

You can use the function reduce to group and the function Object.values to extract the grouped objects.

Inside of the reduce's handler, you need to loop over the request's keys in order to sum up each value.

let array = [        { id: 'ffff55', name: 'f5', card: 'a', request: { device: 0, bus: 1, ship: 21 } },        { id: 'vvvv44', name: 'v4', card: 'c', request: { device: 3, bus: 10, ship: 2 } },        { id: 'cccc33', name: 'c3', card: 'a', request: { device: 0, bus: 1, ship: 2 } },        { id: 'ffff55', name: 'f5', card: 'b', request: { device: 32, bus: 31, ship: 32 } },        { id: 'cccc33', name: 'c3', card: 'e', request: { device: 21, bus: 21, ship: 22 } },        { id: 'cccc33', name: 'c3', card: 'd', request: { device: 4, bus: 1, ship: 2 } },        { id: 'vvvv44', name: 'v4', card: 'c', request: { device: 13, bus: 11, ship: 12 } }    ];
let result = Object.values(array.reduce((a, {id, name, card, request}) => {
  (a[id] || (a[id] = {id, card, name, unique_cards: 1, request: {}}));
  
  if (a[id].card !== card) {
    a[id].unique_cards++;
    a[id].card = card;
  }
  
  Object.keys(request).forEach(k => a[id].request[k] = (a[id].request[k] || 0) + request[k]); 
  return a;
}, Object.create(null)));

result.forEach(o => delete o.card);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

5 Comments

@AmineDa. you're right, so you need to check for the last validated card's value to increase the counter. See the updated answer, unfortunately, the last step should be loop the result and delete the card property.
@AmineDa. basically, I'm asking for a previously captured object by id. So, If a[id] is different than undefined means that I got an object before so I need to work on it, otherwise, is a new id which I didn't get before, so I should create the desired object structure.
@.Ele one more thing. I don't get the point of a[id].card = card inside if
@AmineDa. this is like a breadcrumb, because I need to know if the previously checked card is different in order to increment the count.
yes, but we should check on the whole array of "a[id].card" not only the last value. if i add one more object to the array with an older card, it will count as unique

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.