Удалить объект во вложенном массиве, который имеет значение ключа

Я хочу удалить единственный низкоуровневый объект (например, в приведенном ниже коде под личными данными есть два объекта ... я хочу удалить один объект, где действие: старый) в каждом разделе, где "действие": "СТАРЫЙ"

Я использую lodash в своем проекте

[
  {
    "clientDetails": {
      "personalData": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientAddress": {
      "primaryAddress": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "secondaryAddress": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  },
  {
    "clientDemise": {
      "deathDetails": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientMarital": {
      "divorceInformation": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "marraigeInformation": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  }
]

извините за неправильную презентацию, я впервые задаю вопрос

Какой для этого должен быть о / п?

pritesh 25.10.2018 08:15
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
1
660
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Если структура ваших данных будет достаточно согласованной (т.е. аналогичной той, которую вы включили в свой вопрос), вы можете сделать что-то вроде этого:

const mapObj = (f, obj) => {
    return Object.keys(obj).reduce((acc, key) => {
        acc[key] = f(obj[key], key)
        return acc
    }, {})
}

const filterData = data => {
    // the data itself is an array, so iterate over each item in the array
    return data.map(x1 => {
        // x1 is an object, so need to iterate over each item in the object
        return mapObj(x2 => {
            // x2 is an object, so need to iterate over each item in the object
            return mapObj(x3 => {
                // x3 is an array of objects. each item in the array has an action key which could equal "NEW" or "OLD". get rido of the items with action === "OLD"
                return x3.filter(x4 => x4.action !== "OLD")
            }, x2)
        }, x1)
    })
}

const data = [
  {
    "clientDetails": {
      "personalData": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientAddress": {
      "primaryAddress": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "secondaryAddress": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  },
  {
    "clientDemise": {
      "deathDetails": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientMarital": {
      "divorceInformation": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "marraigeInformation": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  }
]

const result = filterData(data)
console.info(result)

Если вам нужно более общее решение, которое может принимать данные любой структуры и просто удаляет все объекты с действием, равным 'OLD':

const reduceObj = (f, initial, obj) => {
    return Object.keys(obj).reduce((acc, key) => {
        return f(acc, obj[key], key)
    }, initial)
}

const isObject = x => x !== null && typeof x === 'object'

const removeAllOld = data => {
    if (Array.isArray(data)) {
        return data.reduce((acc, value) => {
            // don't include the item if it has a key named 'action' that is equal to 'OLD'
            if (value.action && value.action === 'OLD') return acc

            acc.push(removeAllOld(value))
            return acc
        }, [])
    }
    else if (isObject(data)) {
        return reduceObj((acc, value, key) => {
            // don't include the item if it has a key named 'action' that is equal to 'OLD'
            if (value.action && value.action === 'OLD') return acc

            acc[key] = removeAllOld(value)
            return acc
        }, {}, data)
    }
    else {
        return data
    }
}

const data = [
  {
    "clientDetails": {
      "personalData": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientAddress": {
      "primaryAddress": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "secondaryAddress": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  },
  {
    "clientDemise": {
      "deathDetails": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    },
    "clientMarital": {
      "divorceInformation": [
        {
          "action": "OLD",
          "id": "12345"
        },
        {
          "action": "NEW",
          "id": "12445"
        }
      ],
      "marraigeInformation": [
        {
          "action": "NEW",
          "id": "12345"
        },
        {
          "action": "OLD",
          "id": "12445"
        }
      ]
    }
  }
]

console.info(removeAllOld(data))

Вы можете использовать фильтры JavaScript. Уменьшите размер пакета, не используя lodash.

// it's upto you, you can use new Array() as well and insert if (ktm.action==='NEW')
clients = clients.filter(function(itm) {
  Object.keys(itm).forEach(function(Okey, Ovalue) {
    Object.keys(itm[Okey]).forEach(function(inkey, invalue) {
      itm[Okey][inkey].filter(function(ktm) {
        if (ktm.action === 'OLD') {
          // perform your logic, either you can insert into new Array() or 
          // delete that object and return clients
        }
      });
    });
  });
});
Ответ принят как подходящий

Всего несколько строк могут достичь этого, учитывая

input = your input

Этот кусок кода сделает всю работу

for (var i of input) {
  for (var j in i) {
   var ob = i[j];
   for (var k in ob) {
     var index = _.findIndex(ob[k], {'action': 'OLD'});
     if (index > -1) {
       ob[k].splice(index, 1);
     }
   }
 }
}

Это хорошее короткое решение. Вы можете удалить переменную toRemove, кстати. Кроме того, вы можете превратить это в фрагмент кода и просто включить lodash в качестве внешней библиотеки.

Cully 25.10.2018 09:13

Большое спасибо за предложение, я удалил ненужную переменную, при необходимости создам фрагмент кода.

Shyam Tayal 25.10.2018 09:34

Но это не может быть использовано для удаления многократного ввода нежелательных данных (в случае необходимости).

Koushik Chatterjee 26.10.2018 08:45

ваш код работает ... спасибо .. но он выдает ошибку ob [k]. splice не является функцией, например, в приведенном выше коде, если нет основного адреса @ShyamTayal

deepak reddy yasa 26.10.2018 08:49

Я рассматриваю поля последнего уровня как массив. Если нет, добавьте проверку типа в третьем цикле, чтобы избежать ошибок. Надеюсь, это поможет

Shyam Tayal 26.10.2018 09:00

@ShyamTayal спасибо, что сработало, у меня есть еще одна проблема с этим, это также удаление объекта, который не имеет действия

deepak reddy yasa 26.10.2018 09:18

Добавьте чек if (index > -1), чтобы исправить это, тоже исправлено в решении

Shyam Tayal 26.10.2018 09:37

вы можете сделать глубокую копию вот так:

    const array = [
      {
        "clientDetails": {
          "personalData": [
            {
              "action": "NEW",
              "id": "12345"
            },
            {
              "action": "OLD",
              "id": "12445"
            }
          ]
        },
        "clientAddress": {
          "primaryAddress": [
            {
              "action": "OLD",
              "id": "12345"
            },
            {
              "action": "NEW",
              "id": "12445"
            }
          ],
          "secondaryAddress": [
            {
              "action": "NEW",
              "id": "12345"
            },
            {
              "action": "OLD",
              "id": "12445"
            }
          ]
        }
      },
      {
        "clientDemise": {
          "deathDetails": [
            {
              "action": "NEW",
              "id": "12345"
            },
            {
              "action": "OLD",
              "id": "12445"
            }
          ]
        },
        "clientMarital": {
          "divorceInformation": [
            {
              "action": "OLD",
              "id": "12345"
            },
            {
              "action": "NEW",
              "id": "12445"
            }
          ],
          "marraigeInformation": [
            {
              "action": "NEW",
              "id": "12345"
            },
            {
              "action": "OLD",
              "id": "12445"
            }
          ]
        }
      }
    ]    
    function removeOldAction(a) {
    if (a instanceof Array) {
        let copiee = [];
        for (let item in a) {
            const propValue = removeOldAction(a[item]);
            if (propValue) {
                copiee.push(propValue);
            }
        }
        return copiee;
    }
    if (a instanceof Object) {
        if (a['action'] === 'OLD') { 
            return; 
        }
        let copiee = {};
        for (let key in a) {
            copiee[key] = removeOldAction(a[key]);
        }
        return copiee;
    } 
    return a;
}

    console.info(removeOldAction(array));

Вы можете добиться этого с помощью чего-то вроде этого без lodash:

var data = [{ "clientDetails": { "personalData": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] }, "clientAddress": { "primaryAddress": [{ "action": "OLD", "id": "12345" }, { "action": "NEW", "id": "12445" } ], "secondaryAddress": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] } }, { "clientDemise": { "deathDetails": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] }, "clientMarital": { "divorceInformation": [{ "action": "OLD", "id": "12345" }, { "action": "NEW", "id": "12445" } ], "marraigeInformation": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] } } ]

const removeOld = (data) => data.map(x => 
   Object.entries(x).reduce((r, [k,v]) => {
      r[k] = Object.entries(v).map(([o,p]) => 
        ({[o]: p.filter(n => n.action != 'OLD')}))
      return r
   },{}))

console.info(removeOld(data))
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Использование карта, Object.entries, уменьшать и фильтр.

Другой способ - использовать рекурсию, аналогичную подходу @ Vanojx1, но в ES6:

var data = [{ "clientDetails": { "personalData": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] }, "clientAddress": { "primaryAddress": [{ "action": "OLD", "id": "12345" }, { "action": "NEW", "id": "12445" } ], "secondaryAddress": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] } }, { "clientDemise": { "deathDetails": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] }, "clientMarital": { "divorceInformation": [{ "action": "OLD", "id": "12345" }, { "action": "NEW", "id": "12445" } ], "marraigeInformation": [{ "action": "NEW", "id": "12345" }, { "action": "OLD", "id": "12445" } ] } } ]

const removeOld = (data) => 
  Array.isArray(data) ? data.filter(x => x.action != 'OLD').map(x => removeOld(x)) :
  typeof(data) == 'object' ? Object.entries(data).reduce((r, [k,v]) => (r[k] = removeOld(v), r), {}) : 
  data

console.info(removeOld(data))

Независимая от структуры проверка решения для действий в каждом узле объекта

var data=[{clientDetails:{personalData:[{action:"NEW",id:"12345"},{action:"OLD",id:"12445"}]},clientAddress:{primaryAddress:[{action:"OLD",id:"12345"},{action:"NEW",id:"12445"}],secondaryAddress:[{action:"NEW",id:"12345"},{action:"OLD",id:"12445"}]}},{clientDemise:{deathDetails:[{action:"NEW",id:"12345"},{action:"OLD",id:"12445"}]},clientMarital:{divorceInformation:[{action:"OLD",id:"12345"},{action:"NEW",id:"12445"}],marraigeInformation:[{action:"NEW",id:"12345"},{action:"OLD",id:"12445"}]}}];

const reducer = (curr) => {
  if (_.isArray(curr))
    return _(curr)
      .filter(el => !('action' in el && el.action == 'OLD'))
      .map(el => reducer(el))
      .value()
  else if (_.isObject(curr)) {
    return _(curr)
      .mapValues(el => reducer(el))
      .value()
  } else
    return curr;
};

console.info(reducer(data));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Давайте не будем изменять исходные входные данные, клонировать их с помощью настройщика и отклонять нежелательные элементы (если они есть) внутри настройщика, чтобы получить более чистый клонированный вывод, как ожидалось. Вы можете использовать lodash # cloneDeepWith

_.cloneDeepWith(input, v => _.find(v, {action: "OLD"}) ? _.reject(v, {action: "OLD"}) : undefined);

Это просто пример (жестко запрограммированного) того, что вы хотите отклонить. но вы можете обернуть это в обратный вызов и принять критерии отклонения в качестве аргумента, чтобы сделать его динамичным.

Итак, начнем:

let input = [{"clientDetails":{"personalData":[{"action":"NEW","id":"12345"},{"action":"OLD","id":"12445"}]},"clientAddress":{"primaryAddress":[{"action":"OLD","id":"12345"},{"action":"NEW","id":"12445"}],"secondaryAddress":[{"action":"NEW","id":"12345"},{"action":"OLD","id":"12445"}]}},{"clientDemise":{"deathDetails":[{"action":"NEW","id":"12345"},{"action":"OLD","id":"12445"}]},"clientMarital":{"divorceInformation":[{"action":"OLD","id":"12345"},{"action":"NEW","id":"12445"}],"marraigeInformation":[{"action":"NEW","id":"12345"},{"action":"OLD","id":"12445"}]}}],
    clear = (input, rej) => (
      _.cloneDeepWith(input, v => _.find(v, rej) ? _.reject(v, rej) : undefined)
    ),
    res;
  
res = clear(input, {action: "OLD"}); //you can filter out action: OLD
console.info(res);

res = clear(input, {action: "NEW"}); //you can filter out action: NEW
console.info(res);

res = clear(input, d => d.action== = "OLD"); //you can filter with custom callback with complex logic
console.info(res);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Другие вопросы по теме