通过数组过滤掉JSON

时间:2016-07-19 02:11:26

标签: javascript json

我有一个JSON文件

A1:A50

所有id都是唯一的,并说我有一系列被禁止的ID [" 123"," 423"]我想删除所有的条目数组中的id号(以便输出I' d如下)。

{
    "data": [
        {
            "name": "Jake",
            "id": "123"
        },
        {
            "name": "Bob",
            "id": "234"
        }]
}

如果在JSON和数组中有几千个条目,那么在普通计算机上运行几秒钟(如果在普通计算机上运行几秒钟)会是什么?

5 个答案:

答案 0 :(得分:2)

您可以将Array.prototype.filter()方法与.indexOf()结合使用:



var bannedIds = ["123", "423"];
var input = {
    "data": [
        {
            "name": "Jake",
            "id": "123"
        },
        {
            "name": "Bob",
            "id": "234"
        }]
};

input.data = input.data.filter(function(v) {
  return bannedIds.indexOf(v.id) === -1;
});

console.log(input);




如果您不想覆盖原始数组,只需将.filter()调用的结果分配给新变量。

如果上述结果对于您的大量数据而言太慢,您可以尝试使用传统的.filter()循环替换for和/或使用查找替换.indexOf()从被禁止的id数组创建的对象。

答案 1 :(得分:1)

如果您可以使用ES6,则可以执行以下操作:



const source = {
    "data": [
        {
            "name": "Jake",
            "id": "123"
        },
        {
            "name": "Bob",
            "id": "234"
        }
    ]
};
const banned = ["123", "423"];

// O(n) startup cost for constant access time later
const bannedSet = new Set(banned);

// O(n)
const result = source.data.filter(x => !bannedSet.has(x.id));

console.log(result);




正如评论中所提到的,创建Set会产生启动成本。但是,这可以让您调用Set.prototype.has,这是常量。

然后,它只是迭代每个元素并过滤掉禁止集中的元素。

如果您不能使用ES6,则可以用普通的JS对象替换Set。如果你必须支持IE< 9,请使用polyfill Array.prototype.filter(感谢@nnnnnn)。

<强>更新

@SpencerWieczorek指出ES6 spec似乎表示Set.prototype.has迭代。我过早地谈到了查找是不变的(我从其他语言中继承了我的经验)。通常,集合将比O(n)更好,例如,常量或O(log n)取决于底层实现。您的里程可能会有所不同,因此在某些情况下nnnnnn's answer可能会更快。

尝试使用大量数据来确认一些解决方案。

答案 2 :(得分:0)

修改

我回避使用filter之类的东西,因为这涉及到创建一个新阵列。对于我们正在讨论的数据大小,这实际上可能很好,但我在下面的方法更有效。

在我的笔记本电脑上,整个程序运行大约0.2秒。 (它使用10,000个条目和100个禁止的ID。)

var o = {
    data: []
};

for (var i = 0; i < 10000; i++) {
    o.data.push({
        name: i % 2 === 0 ? 'Jake' : 'Bob', // couldn't think of more names :-)
        id: ''+i // convert to string
    });
}

var banned = {};

for (var i = 0; i < 100; i++) {
    banned[''+(i * 3)] = true; // ban 0, 3, 6, 9, 12, ...
}

for (var i = o.data.length - 1; i >= 0; i--) {
    if (banned[o.data[i].id]) {
        o.data.splice(i, 1);
    }
}

console.log(o);

// { data:
//    [ { name: 'Bob', id: '1' },
//      { name: 'Jake', id: '2' },
//      { name: 'Jake', id: '4' },
//      { name: 'Bob', id: '5' },
//      { name: 'Bob', id: '7' },
//      { name: 'Jake', id: '8' },
//      { name: 'Jake', id: '10' },
//      ...

答案 3 :(得分:0)

我假设您已经解析了JSON数据,并且您有一个指向要过滤的数组的变量。此外,你有一个数组与&#34;禁止&#34;的ID。

var data = [{
        "name": "Jake",
        "id": "123"
    }, {
        "name": "Bob",
        "id": "234"
    }, {
        "name": "Joe",
        "id": "345"
    }];

var banned = ["123", "345"];

以下功能可能会在性能方面做得最好:

// Modifies the data array "in place", removing all elements
// whose IDs are found in the "banned" array
function removeBanned(data, banned) {
    // Index the "banned" IDs by writing them as the properties
    // of a JS object for really quick read access later on
    var bannedObj = {};
    banned.forEach(function(b) { bannedObj[b] = true; });

    var index = data.length - 1;

    while (index >= 0) {
        if (bannedObj[data[index].id]) {
            data.splice(index, 1);
        }
        --index;
    }
}

答案 4 :(得分:0)

这个似乎足够快,但我建议你制作一个免费的干净副本,而不是修改现有的数组, - 它可能会更快。

function filterout(o,p,f) {
  var i = 0; f = f.join(); 
  while( o[i] ) {
    if( f.match( o[i][p] ) ){ o.splice(i,1) }
    i++ 
  };
}

var filter = ["123","423"];

var object =
    {
    "data": [
        {
            "name": "John",
            "id": "723"
        },
        {
            "name": "Jake",
            "id": "123"
        },
        {
            "name": "Bob",
            "id": "234"
        }]
};

filterout( object.data, "id", filter );

console.log(JSON.stringify( object ));