我有一个JSON文件
A1:A50
所有id都是唯一的,并说我有一系列被禁止的ID [" 123"," 423"]我想删除所有的条目数组中的id号(以便输出I' d如下)。
{
"data": [
{
"name": "Jake",
"id": "123"
},
{
"name": "Bob",
"id": "234"
}]
}
如果在JSON和数组中有几千个条目,那么在普通计算机上运行几秒钟(如果在普通计算机上运行几秒钟)会是什么?
答案 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 ));