我如何从递归 $.each 中的对象中删除元素

How i can delete elements from object in recursive $.each?

本文关键字:对象 删除 元素 each 递归      更新时间:2023-09-26

例如,我有这个数据对象:

var data = {
    'some': [
        {'id': 10, 'info': [{'next': 11}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 11, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 12, 'info': [{'next': 0},  {'next': 0}, {'next': 20}, {'next':  0}]}, 
        {'id': 13, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 14, 'info': [{'next': 12}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 15, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 16, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 14}]}, 
        {'id': 17, 'info': [{'next': 0},  {'next': 0}, {'next': 13}, {'next':  0}]}, 
        {'id': 18, 'info': [{'next': 15}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 11}]}, 
        {'id': 20, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}
    ]
};

我想删除所有包含id next元素,例如,从上面的数据对象中删除,我想得到这样的东西

    var data = {
        'some': [
            {'id': 10, 'info': [{'next': 11}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
            {'id': 16, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 14}]}, 
            {'id': 17, 'info': [{'next': 0},  {'next': 0}, {'next': 13}, {'next':  0}]}, 
            {'id': 18, 'info': [{'next': 15}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
            {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
            {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 11}]}, 
        ]
    };

我写了这个脚本,但它返回Uncaught TypeError: Cannot read property 'id' of undefined,为什么?

var cleanData = function (d

ata) {
    $.each(data['some'], function (_is, some) {
        $.each(some['info'], function (_in, next) {
            if (next['next']) 
                $.each(data['some'], function (_is2, some2) {
                    if (some2['id'] == next['next']) 
                        data['some'].remove(_is2);
                });
        });
    });
    return data;
};

我在JsFiddle上的例子。

谢谢。

您可以通过两个步骤创建它:首先找到任何next对象中包含的所有 ID。然后筛选数组并删除具有该 ID 的行。

例:

// Build ids table
var idsToRemove = data.some.reduce(function(ids, row) {
  return row.info.reduce(function(ids, obj) {
    return ids[obj.next] = true, ids;
  }, ids);
}, {});
// Filter out rows with those IDs
data.some = data.some.filter(function(row) {
  return !idsToRemove[row.id];
});
console.log(data);

var data = {
    'some': [
        {'id': 10, 'info': [{'next': 11}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 11, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 12, 'info': [{'next': 0},  {'next': 0}, {'next': 20}, {'next':  0}]}, 
        {'id': 13, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 14, 'info': [{'next': 12}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 15, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 16, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 14}]}, 
        {'id': 17, 'info': [{'next': 0},  {'next': 0}, {'next': 13}, {'next':  0}]}, 
        {'id': 18, 'info': [{'next': 15}, {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}, 
        {'id': 19, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next': 11}]}, 
        {'id': 20, 'info': [{'next': 0},  {'next': 0}, {'next': 0},  {'next':  0}]}
    ]
};
// Build ids table
var ids = data.some.reduce(function(ids, row) {
  return row.info.reduce(function(ids, obj) {
    return ids[obj.next] = true, ids;
  }, ids);
}, {});
// Filter out rows with those IDs
data.some = data.some.filter(function(row) {
  return !ids[row.id];
});
console.log(data);

Array.prototype.filter 非常适合这样的问题。此代码应生成您要查找的内容:

data.some = data.some.filter(function(item) {
    return item.info.filter(function(i) {
        return i.next > 0;
    }).length > 0;
});

更新:请参阅本页上安德鲁的答案。这是一个更清洁、更安全的解决方案。

简而言之,你不能。相反,您必须使用带有索引的常规for循环,以便您可以跟上数组的新长度。

$.each(data['some'], function (_is, some) {
    $.each(some['info'], function (_in, next) {
        if (next['next']) 
            for(var i=0, len=data['some'].length; i < len; i++) {
                var some2 = data['some'][i];
                if (some2['id'] == next['next']) {
                    data['some'].remove(_is2);
                    // Decrement i since the next item will now be in the place of the one you removed.
                    i--;
                    // Decrement len since your array now holds one less item.
                    len--;
                }
            }
        }
    });
});

使用 for while 长度大于零,并从 array

您遇到的错误是因为并非数组中的每个对象都具有键为"id"

的属性

我不太清楚应该删除什么,但如果是所有东西,第一个关键是"下一个,更改这个:

if (some2['id'] == next['next']) 

对此:

if (some2[0] == 'next') 

工作演示

呵呵,

-泰德