1

I am working with a huge array of objects. Through filtering, I have shrunk the data set. I need to add an array of properties to each object based on properties in another "lookup" object. My initial array of objects looks like so.

const arr = [{id: "12345", type: "square", current: "0", max: "1", code: "50"}, 
             {id: "23456", type: "square", current: "0", max: "3", code: "50"},
             {id: "54321", type: "square", current: "2", max: "4", code: "50"},
             {id: "54321", type: "circle", current: "0", max: "1", code: "100"}, 
             {id: "65432", type: "circle", current: "3", max: "3", code: "100"},
             {id: "76543", type: "circle", current: "0", max: "2", code: "100"}]

I have a "lookup" object. The basis of the object is for each type and code there is a level 0 to 3. For each object above, I need to add the title property for each id that matches type and code from current to max. For this example I simplified the "lookup" object.

const lookup = [{title: "yes", code: "50", level: "0", type: "square"},
                {title: "no", code: "50", level: "1", type: "square"}, 
                {title: "maybe", code: "50", level: "2", type: "square"},
                {title: "sure", code: "50", level: "3", type: "square"},
                {title: "up", code: "100", level: "0", type: "circle"},
                {title: "down", code: "100", level: "1", type: "circle"},
                {title: "left", code: "100", level: "2"}, type: "circle"},
                {title: "right", code: "100", level: "3"}, type: "circle"}]

So my resulting array of objects would look something like so

const result = [{id: "12345", type: "square", current: "0", max: "1", code: "50", titles: ["yes", "no"]}, 
                {id: "23456", type: "square", current: "0", max: "3", code: "50", titles: ["yes", "no", "maybe", "sure"]},
                {id: "54321", type: "square", current: "2", max: "4", code: "50", titles: ["maybe", "sure"]},
                {id: "54321", type: "circle", current: "0", max: "2", code: "100", titles: ["up", "down"]}, 
                {id: "65432", type: "circle", current: "3", max: "3", code: "100", titles: ["right"]},
                {id: "76543", type: "circle", current: "0", max: "2", code: "100", titles: ["up", "down", "left"]}]

Is there a elegant way to do this without iterating over every single combination of type, code, and level?

5
  • Have you tried anything? Commented Aug 17, 2018 at 16:07
  • Did you make that lookup object yourself or did get it from somewhere else? i.e. Can you restructure it in another way? Commented Aug 17, 2018 at 16:09
  • @ibrahimmahrir the lookup object is being supplied to me, but it is static data so I could restructure it if needed. Commented Aug 17, 2018 at 16:24
  • One more question, are the level numbers sparse? i.e Can there be level 1 and 3 without a level 2? Commented Aug 17, 2018 at 16:28
  • Also how come there is a max: 4 for the third object, where there is only 3 levels? Do we have to care for this? What should be do in this case? Commented Aug 17, 2018 at 16:56

1 Answer 1

1

First, let's transform the lookup array into a nested tree, that way the lookup for the titles will be fairly simple:

const lookupTree = lookup.reduce((acc, o) => {
    var byType = acc[o.type] = acc[o.type] || {};
    var byCode = byType[o.code] = byType[o.code] || {};
    byCode[o.level] = o.title;
    return acc;
}, {});

This will result in a tree structure like this:

{
   "square": {
      "50": {
         "0": "yes",
         "1": "no",
         "2": "maybe",
         "3": "sure"
      }
   },
   "circle": {
      "100": {
         "0": "up",
         "1": "down",
         "2": "left",
         "3": "right"
      }
   }
}

Now for each object in the array arr, we just loop from current to max (inclusive) and map each level to its equivalent title, by simple traversing the tree above first by type then by code and finally by level (we first check if those exist, i.e. if there is a type for the current object in the lookup tree, if there is a code for it and if there is a level too):

arr.forEach(o => {
    o.titles = [];
    for(var i = o.current; i <= o.max; i++) {
        if(lookupTree[o.type] && lookupTree[o.type][o.code] && lookupTree[o.type][o.code][i]) {
            o.titles.push(lookupTree[o.type][o.code][i]);
        }
    }
});

Example:

const arr = [{"id":"12345","type":"square","current":"0","max":"1","code":"50"},{"id":"23456","type":"square","current":"0","max":"3","code":"50"},{"id":"54321","type":"square","current":"2","max":"4","code":"50"},{"id":"54321","type":"circle","current":"0","max":"1","code":"100"},{"id":"65432","type":"circle","current":"3","max":"3","code":"100"},{"id":"76543","type":"circle","current":"0","max":"2","code":"100"}];
const lookup = [{"title":"yes","code":"50","level":"0","type":"square"},{"title":"no","code":"50","level":"1","type":"square"},{"title":"maybe","code":"50","level":"2","type":"square"},{"title":"sure","code":"50","level":"3","type":"square"},{"title":"up","code":"100","level":"0","type":"circle"},{"title":"down","code":"100","level":"1","type":"circle"},{"title":"left","code":"100","level":"2","type":"circle"},{"title":"right","code":"100","level":"3","type":"circle"}];

const lookupTree = lookup.reduce((acc, o) => {
    var byType = acc[o.type] = acc[o.type] || {};
    var byCode = byType[o.code] = byType[o.code] || {};
    byCode[o.level] = o.title;
    return acc;
}, {});

arr.forEach(o => {
    o.titles = [];
    for(var i = o.current; i <= o.max; i++) {
        if(lookupTree[o.type] && lookupTree[o.type][o.code] && lookupTree[o.type][o.code][i]) {
            o.titles.push(lookupTree[o.type][o.code][i]);
        }
    }
});

console.log(arr);

Note: If you don't want to alter the original array arr, then just use map instead of forEach and clone the objects before adding the title property to them.

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

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.