Swarup Chavan
Swarup Chavan

Reputation: 216

Deleting data from a complex array structure based on multiple condition

I'm receiving the json data in the below format

[
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1"
            },
            {
               "id":"1.2"
            }
         ],
         "questionId":"1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               
               "id":"1.1.1.1"
            },
            {
               "id":"1.1.1.2"
            },
            {
               "id":"1.1.1.3",
            }
         ],
         "questionId":"1.1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {

               "id":"1.1.1.3.1.1" 
            },
            {
               "id":"1.1.1.3.1.2"
            }
         ],
         "questionId":"1.1.1.3"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1.1.3.1.1.1.1"
            },
            {
               "id":"1.1.1.3.1.1.1.2"
            }
         ],
         "questionId":"1.1.1.3.1.1"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            {
               "id":"2.1"
            },
            { 
               "id":"2.2"
            }
         ],
         "questionId":"2"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            
         ],
         "questionId":"2.2"
      },
      }
]

and I want to delete the record from this array based on multiple condition which is as followed

  1. The "key" ,suppose i pass key as 4 the only the records which has key as 4 should be considered for deletion nothing from key as 5 should be deleted
  2. the second is the id suppose the id(this is inside choice) I get is "1.1.1.2" then only the records after that should be deleted

so for eg I get key as 4 and id as "1.1.1.2" then the expected output should be as followed

[

  {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1"
            },
            {
               "id":"1.2"
            }
         ],
         "questionId":"1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               
               "id":"1.1.1.1"
            },
            {
               "id":"1.1.1.2"
            },
            {
               "id":"1.1.1.3",
            }
         ],
         "questionId":"1.1"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            {
               "id":"2.1"
            },
            { 
               "id":"2.2"
            }
         ],
         "questionId":"2"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            
         ],
         "questionId":"2.2"
      },
      }
]

I tried using splice inside forEach but seems with splice there is an unusual behavior when used inside foreach anyother approach for the same

My code that i was trying

  this.followUpQues.forEach(function(val,index,object) { 
    if(val.data.choice.filter(y=>y.id === item.id).length >= 1) {
          keyNumber = val.key;
          valueIndex = index;
    }
 }) 

so after getting key and index i tried to delete the records after the index found and having key value that is identified,but using splice inside the foreach has weird behaviour

Upvotes: 1

Views: 63

Answers (4)

karthicvel
karthicvel

Reputation: 371

Avoid nested if conditions

    choiceFound = 0
    for(let i = 0; i < questions.length; i++ ){
        let question = questions[i];
        if(question.key == 4 && !choiceFound){
           choiceFound = question.data.choice.find(c => c.id == "1.1.1.2") ? 1: 0;
         }
         else {
                questions.splice(i, 1); 
                i--;
            }
        }

Upvotes: 0

Weilory
Weilory

Reputation: 3111

let json = [
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1"
            },
            {
               "id":"1.2"
            }
         ],
         "questionId":"1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               
               "id":"1.1.1.1"
            },
            {
               "id":"1.1.1.2"
            },
            {
               "id":"1.1.1.3",
            }
         ],
         "questionId":"1.1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {

               "id":"1.1.1.3.1.1" 
            },
            {
               "id":"1.1.1.3.1.2"
            }
         ],
         "questionId":"1.1.1.3"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1.1.3.1.1.1.1"
            },
            {
               "id":"1.1.1.3.1.1.1.2"
            }
         ],
         "questionId":"1.1.1.3.1.1"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            {
               "id":"2.1"
            },
            { 
               "id":"2.2"
            }
         ],
         "questionId":"2"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            
         ],
         "questionId":"2.2"
      },
      }
];

let inspect = (json, key, id) => json.map((it, i) => it.key !== key || i === 0 ? it : json[i-1].data.choice.map((k, v)=>k.id).includes(id) ? null : it).filter(it => it !== null);

console.log(inspect(json, 4, '1.1.1.2'));

Update

If you mean deleting everything after "1.1.1.2" appears, then

let inspect = (json, key, id) => {
   let processed = json.map((it, i) => it.key !== key || i === 0 ? it : json[i-1].data.choice.map((k, v)=>k.id).includes(id) ? null : it);
   return processed.filter((it, i)=>
       it == null ? false : it.key !== key || i < processed.indexOf(null)
   );
};

let res = inspect(json, 4, '1.1.1.2');
console.log(res);

Upvotes: 0

Brenden
Brenden

Reputation: 2097

This problem could be broken down into two steps. First finding the first index that matches your desired predicate, then filtering the result set after the index over a give key. If you want to be most efficient, you can combine these steps, but code readability will suffer.

const data = [
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1"
            },
            {
               "id":"1.2"
            }
         ],
         "questionId":"1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               
               "id":"1.1.1.1"
            },
            {
               "id":"1.1.1.2"
            },
            {
               "id":"1.1.1.3",
            }
         ],
         "questionId":"1.1"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {

               "id":"1.1.1.3.1.1" 
            },
            {
               "id":"1.1.1.3.1.2"
            }
         ],
         "questionId":"1.1.1.3"
      }
   },
   {
      "key":4,
      "data":{
         "choice":[
            {
               "id":"1.1.1.3.1.1.1.1"
            },
            {
               "id":"1.1.1.3.1.1.1.2"
            }
         ],
         "questionId":"1.1.1.3.1.1"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            {
               "id":"2.1"
            },
            { 
               "id":"2.2"
            }
         ],
         "questionId":"2"
      }
   },
   {
      "key":5,
      "data":{
         "choice":[
            
         ],
         "questionId":"2.2"
      },
      }
];

const remove = (data, key, id) => {
  let result = data;
 
  // find first index that matches our predicate.
  // first the key has to match, and then the id must be contained within our choices.
  const index = data.findIndex((n) => {
    return n.key === key && n.data.choice.findIndex((m) => m.id === id) !== -1;
  });
 
  // did we find something? If so start filtering!
  if (index !== -1) {
    result = data.filter((n, i) => {
      // is this element before our filter index? or maybe its not the right key?
      // if either are true, keep the element.
      return i <= index || n.key !== key;
    });
 }
 
 return result;
};

console.log(remove(data, 4, "1.1.1.2"));

Upvotes: 0

Ravi
Ravi

Reputation: 2281

You can do this using simple for loop:

choiceFound = 0
for(let i = 0; i < questions.length; i++ ){
    let question = questions[i];
    if(question.key == 4){
        if(!choiceFound) {
            choiceFound = question.data.choice.find(c => c.id == "1.1.1.2") ? 1: 0;
        }
        else {
            questions.splice(i, 1); 
            i--;
        }
    }
}

Upvotes: 1

Related Questions