1

I have two arrays of objects, that look like this:

const data = [
  {
    id: 1,
    condition: 1,
    helpers: [{id: 1, condition: null}, {id: 2, condition: 2}]
  },
  {
    id: 2,
    condition: null,
    helpers: [{id: 1, condition: 1}, {id: 2, condition: null}]
  }
]

const conds = [
  {
    id: 1,
    conditions: {
       rules: ['test', 'foo']
    }
  },
  {
    id: 2,
    conditions: {
       rules: ['#hashtag', 'foo']
    }
  }
]

What I try to achieve is, that I want to replace the condition values of the data array with the ones in the conds array.

My solution, which does not work quite well looks like this:

let newArray = [];

data.forEach(obj => {
        conds.forEach(cond => {
            if (obj.condition) {
                if (obj.condition === cond.id) {
                    obj.condition = cond.conditions.rules;
                    newArray.push(obj);
                }
            } else {
                obj.helpers.forEach(h => {
                    if (h.condition && h.condition === cond.id) {
                        h.condition = cond.conditions.rules;
                        newArray.push(obj);
                    }
                });
            }
        })
    });

I feel like I am pretty close to the solution since my newArray contains the changes properties, but not for the last item inside of helpers, whereas the condition property is still 2.

The output should look like this:

[
  {
     id: 1
     condition: ['test', 'foo'],
     helpers: [{id: 1, condition: null}, {id: 2, condition: ['#hashtag', 'foo']}]
  },
  {
     id: 2
     condition: null,
     helpers: [{id: 1, condition: ['test', 'foo']}, {id: 2, condition: null}]
  },
]

What am I missing here?

Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
wasddd_
  • 937
  • 2
  • 10
  • 19

3 Answers3

2

Got it working:

const finalData = data.map(dataItem => {
  dataItem.condition = dataItem.condition ? rulesMap[dataItem.condition] : null;
  dataItem.helpers.map(item => {
    item.condition = item.condition ? rulesMap[item.condition] : null
  })
  return dataItem;
});
wasddd_
  • 937
  • 2
  • 10
  • 19
0

Loop through the data array using forEach get the id then filter the conds array with it using find() to get the related conditions.rules like:

data.forEach(function(item) {
    item.condition = conds.find(x => x.id === item.id).conditions.rules;
});

Working fiddle:

const data = [{
    id: 1,
    condition: 1,
    helpers: [{id: 1, condition: null}, {id: 2, condition: 2}]
  },{
    id: 2,
    condition: null,
    helpers: [{id: 1, condition: 1}, {id: 2, condition: null}]
}];

const conds = [{
    id: 1,
    conditions: {
       rules: ['test', 'foo']
    }
  },{
    id: 2,
    conditions: {
       rules: ['#hashtag', 'foo']
    }
}];

data.forEach(function(item) {
  item.condition = conds.find(x => x.id === item.id).conditions.rules;
});

console.log(data);
Zakaria Acharki
  • 66,747
  • 15
  • 75
  • 101
  • Every time you use find, inside the loop, you create another loop. Imagine two giant arrays, it will take forever to finish. I think mapping the conditions is the less expensive way of doing it as I wrote in my answer. – Bruno João Oct 26 '18 at 15:09
  • hey @zakaria, unfortunately this is not a working example. The conditions inside of the `helpers` array should also be mapped to the conditions. – wasddd_ Oct 26 '18 at 18:34
0

const data = [
  {
    id: 1,
    condition: 1,
    helpers: [{id: 1, condition: null}, {id: 2, condition: 2}]
  },
  {
    id: 2,
    condition: null,
    helpers: [{id: 1, condition: 1}, {id: 2, condition: null}]
  }
]

const conds = [
  {
    id: 1,
    conditions: {
       rules: ['test', 'foo']
    }
  },
  {
    id: 2,
    conditions: {
       rules: ['#hashtag', 'foo']
    }
  }
]

// START SOLUTION

const rulesMap = conds.reduce((map, condition) => {
    map[condition.id] = condition.conditions.rules;
    return map;
}, {});

const finalData = data.map(dataItem => {
    dataItem.condition = dataItem.condition ? rulesMap[dataItem.condition] : null;
    return dataItem;
});

// END SOLUTION

console.log(finalData);

Create a map of conditions:

const rulesMap = conds.reduce((map, condition) => {
    map[condition.id] = condition.conditions.rules;
    return map;
}, {});

Get the new data list with condition rules replaced:

const finalData = data.map(dataItem => {
    dataItem.condition = dataItem.condition ? rulesMap[dataItem.condition] : null;
    return dataItem;
});
Bruno João
  • 5,105
  • 2
  • 21
  • 26
  • I get the error `reduction is not defined` in this :/ – wasddd_ Oct 26 '18 at 15:10
  • I've just changed the map constructor to use less memory. `rulesMap` make smore sense here as we do not care about other properties. – Bruno João Oct 26 '18 at 15:14
  • hey @Bruno - this is unfortunately not the solution as I have expected. Please see the expected output in my question - actually your solution returns the same as my version. :/ The condition inside of the `helpers` array should also be mapped to the conditions. – wasddd_ Oct 26 '18 at 18:32
  • Works with this logic using your rulesmap: ```const finalData = data.map(dataItem => { dataItem.condition = dataItem.condition ? rulesMap[dataItem.condition] : null; dataItem.helpers.map(item => { item.condition = item.condition ? rulesMap[item.condition] : null }) return dataItem; });``` – wasddd_ Oct 27 '18 at 16:31