2

There is an input structure with rules nested inside other rules. In the rules array, wherever there is a 'data' property, its value has to be changed to "foo"

Sample input objects:

  1. {condition: 'and', rules: [{data: '123'}]}

  2. {condition: 'or', rules: [ { data: '123'}, {condition: 'and', rules: [{data:'123'},{ data:'456'}] }]

Am recursively calling a function to iterate over and if the item has data property, changing its value

My function:

function iterateRules(input) {
    input.rules.map(function(item) {
      if(_.has(item, "rules")){
        this.iterateRules(item); //bug-needs extra check like accepted answer 
      } else if(_.has(item, “data”)){
         return item.data = “foo”;
      }
    }, this);
   return input;
 }
Rk R Bairi
  • 1,289
  • 7
  • 15
  • 39
  • It would be helpful if you examples used regular, straight quotes and didn't have syntax errors like `[value: ‘456”]` – Mark Jan 17 '19 at 04:04
  • Also, do you need to change the item in place or return a new item? – Mark Jan 17 '19 at 04:10
  • @MarkMeyer I wanted to return this whole changed object. My bug in the code was , I was not returning and the extra check if it has rules to recursive call helped (like in approved answer) – Rk R Bairi Jan 17 '19 at 18:36

2 Answers2

2

There is a potential bug in the code you mentioned.

  1. In the recursive call to iterateRules you are passing input instead of item
  2. You also need to check if the input has rules property

Try this -

function iterateRules(input) {
  if(_.has(input, "rules")) {
    input.rules.map(function(item) { 
      if(_.has(item, "rules")){
        this.iterateRules(item);
      } else if (_.has(item, "data")) {
          return item.data = "foo";
      }
    }, this);
    console.log(input);
  }
}
Rishikesh Dhokare
  • 3,559
  • 23
  • 34
  • passing input instead of item was a typo here. But the extra condition helped. And was not returning the input to the caller of this function previously. – Rk R Bairi Jan 17 '19 at 18:37
1

There is a recursive approach to achieve this:

const input = {condition: "and", rules: [ { data: "123"}, {condition: "and", rules: [{data:"456"}, {condition: "and", rules: [{value: "456"}]} ] } ]}

function test (obj) {
 if(!Object.keys(obj).includes('rules')) return;
 obj.rules.forEach(x => x.data ? x.data = 'foo' : x);
 return test(obj.rules.find(x => !Object.keys(x).includes('data')));
}

test(input)

console.log(input);

note: this function changes input obj.

guijob
  • 4,413
  • 3
  • 20
  • 39