Я хочу удалить единственный низкоуровневый объект (например, в приведенном ниже коде под личными данными есть два объекта ... я хочу удалить один объект, где действие: старый) в каждом разделе, где "действие": "СТАРЫЙ"
Я использую 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"
}
]
}
}
]
извините за неправильную презентацию, я впервые задаю вопрос



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если структура ваших данных будет достаточно согласованной (т.е. аналогичной той, которую вы включили в свой вопрос), вы можете сделать что-то вроде этого:
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 в качестве внешней библиотеки.
Большое спасибо за предложение, я удалил ненужную переменную, при необходимости создам фрагмент кода.
Но это не может быть использовано для удаления многократного ввода нежелательных данных (в случае необходимости).
ваш код работает ... спасибо .. но он выдает ошибку ob [k]. splice не является функцией, например, в приведенном выше коде, если нет основного адреса @ShyamTayal
Я рассматриваю поля последнего уровня как массив. Если нет, добавьте проверку типа в третьем цикле, чтобы избежать ошибок. Надеюсь, это поможет
@ShyamTayal спасибо, что сработало, у меня есть еще одна проблема с этим, это также удаление объекта, который не имеет действия
Добавьте чек if (index > -1), чтобы исправить это, тоже исправлено в решении
вы можете сделать глубокую копию вот так:
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>
Какой для этого должен быть о / п?