我想了解从另一个元素的所有元素中过滤数组的最佳方法。我试过过滤器功能,但它没有告诉我如何给它我想要删除的值。
有点像:
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallback);
// filteredArray should now be [1,3]
function myCallBack(){
return element ! filteredArray;
//which clearly can't work since we don't have the reference <,<
}
如果过滤功能没用,你会如何实现?
编辑:我检查了可能的重复问题,这对于那些容易理解javascript的人来说非常有用。检查得很好的答案让事情变得简单。
答案 0 :(得分:102)
您可以使用this
函数的filter()
参数来避免将过滤器数组存储在全局变量中。
var filtered = [1, 2, 3, 4].filter(
function(e) {
return this.indexOf(e) < 0;
},
[2, 4]
);
console.log(filtered);
答案 1 :(得分:83)
我会这样做;
var arr = [1,2,3,4],
brr = [2,4],
res = arr.filter(f => !brr.includes(f));
console.log(res);
答案 2 :(得分:28)
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(myCallBack);
function myCallBack(el){
return anotherOne.indexOf(el) < 0;
}
在回调中,检查array
的每个值是否在anotherOne
https://jsfiddle.net/0tsyc1sx/
如果您使用lodash.js
,请使用_.difference
filteredArray = _.difference(array, anotherOne);
如果你有一个对象数组:
var array = [{id :1, name :"test1"},{id :2, name :"test2"},{id :3, name :"test3"},{id :4, name :"test4"}];
var anotherOne = [{id :2, name :"test2"}, {id :4, name :"test4"}];
var filteredArray = array.filter(function(array_el){
return anotherOne.filter(function(anotherOne_el){
return anotherOne_el.id == array_el.id;
}).length == 0
});
答案 3 :(得分:13)
/* Here's an example that uses (some) ES6 Javascript semantics to filter an object array by another object array. */
// x = full dataset
// y = filter dataset
let x = [
{"val": 1, "text": "a"},
{"val": 2, "text": "b"},
{"val": 3, "text": "c"},
{"val": 4, "text": "d"},
{"val": 5, "text": "e"}
],
y = [
{"val": 1, "text": "a"},
{"val": 4, "text": "d"}
];
// Use map to get a simple array of "val" values. Ex: [1,4]
let yFilter = y.map(itemY => { return itemY.val; });
// Use filter and "not" includes to filter the full dataset by the filter dataset's val.
let filteredX = x.filter(itemX => !yFilter.includes(itemX.val));
// Print the result.
console.log(filteredX);
答案 4 :(得分:5)
如果您需要比较对象数组,则在所有情况下均适用:
let arr = [{ id: 1, title: "title1" },{ id: 2, title: "title2" }]
let brr = [{ id: 2, title: "title2" },{ id: 3, title: "title3" }]
const res = arr.filter(f => brr.some(item => item.id === f.id));
console.log(res);
答案 5 :(得分:5)
您的问题有很多答案,但是我看不到有人使用lambda表达式:
var array = [1,2,3,4];
var anotherOne = [2,4];
var filteredArray = array.filter(x => anotherOne.indexOf(x) < 0);
答案 6 :(得分:3)
这是相对于另一个数组过滤数组的最简单方法。两个数组都可以在其中包含对象而不是值。
let array1 = [1,3,47,1,6,7];
let array2 = [3,6];
let filteredArray1 = array1.filter(el => array2.includes(el));
filteredArray1 == [3,6] \\这些是过滤器之后array1的值
答案 7 :(得分:3)
OA也可以按以下方式在ES6中实现
ES6:
const filtered = [1, 2, 3, 4].filter(e => {
return this.indexOf(e) < 0;
},[2, 4]);
答案 8 :(得分:3)
上述所有解决方案都“有效”,但效果并不理想,并且都是以同样的方式解决问题,即使用Array.prototype.indexOf或Array.prototype.includes线性搜索每个点的所有条目。一个更快的解决方案(甚至比大多数情况下的二进制搜索要快得多)将是对数组进行排序并在前进时向前跳,如下所示。但是,一个缺点是这需要数组中的所有条目都是数字或字符串。然而,二进制搜索在某些罕见情况下可能比逐行线性搜索更快。这些情况源于我的渐进线性搜索具有 O(2n 1 + n 2 )(仅 O)的复杂性(n 1 + n 2 )在更快的C / C ++版本中)(其中 n 1 是搜索到的数组, n 2 是过滤器数组),而二进制搜索的复杂度为 O(n 1 ceil(log 2 n 2 ))(ceil =向上舍入 - 到 ceil ing),最后, indexOf搜索在 O(n 1 )和 O(n 1 n 2 >之间具有高度可变的复杂性),平均到 O(n 1 ceil(n 2 ÷2))。因此,在(n 1 ,n 2 )等于 {1的情况下,indexOf平均只会是最快的,2} , {1,3} 或 {x,1 |x∈N} 。然而,这仍然不是现代硬件的完美代表。 IndexOf在大多数现代浏览器中都可以在最大程度上进行本地优化,使其非常符合branch prediction的规律。因此,如果我们对indexOf做出与渐进线性和二进制搜索相同的假设 - 数组被预先排序 - 那么,根据链接中列出的统计数据,我们可以预期IndexOf的速度大约是6倍,将其复杂性转移到 O(n 1 ÷6)和 O(n 1 n 2 之间),平均到 O(n 1 ceil(n 2 7÷12))。最后,请注意以下解决方案永远不会与对象一起使用,因为在javascript中无法获取内部对象指针(用于数值比较)。
function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); }
function sortIntArray(a,b) { return (a|0) - (b|0) |0; }
const Math_clz32 = Math.clz32 || (function(log, LN2){
return function(x) {
return 31 - log(x >>> 0) / LN2 | 0; // the "| 0" acts like math.floor
};
})(Math.log, Math.LN2);
function filterArrayByAnotherArray(searchArray, filterArray, i = 0) {
if (
// NOTE: This does not check the whole array. But, if you know
// that there are only strings or numbers (not a mix of
// both) in the array, then this is a safe assumption.
// Always use `==` with `typeof` because browsers can optimize
// the `==` into `===` (ONLY IN THIS CIRCUMSTANCE)
typeof searchArray[0] == "number" &&
typeof filterArray[0] == "number" &&
(searchArray[0]|0) === searchArray[0] &&
(filterArray[0]|0) === filterArray[0]
) {filterArray
// if all entries in both arrays are integers
searchArray.sort(sortIntArray);
filterArray.sort(sortIntArray);
} else {
searchArray.sort(sortAnyArray);
filterArray.sort(sortAnyArray);
}
var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
var progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
// After computing the complexity, we can predict which algorithm will be the fastest
if (progressiveLinearComplexity < binarySearchComplexity) {
// Progressive Linear Search
return searchArray.filter(function(currentValue){
while (filterArray[i] < currentValue) ++i;
// +undefined = NaN, which is always false for <, avoiding an infinite loop
return filterArray[i] !== currentValue;
});
} else {
// Binary Search
return searchArray.filter(
fastestBinarySearch(filterArray)
);
}
}
// see https://stackoverflow.com/a/44981570/5601591 for implementation
// details about this binary search algorithim
function fastestBinarySearch(array){
var initLen = (array.length|0) - 1 |0;
const compGoto = Math_clz32(initLen) & 31;
return function(ARG_sValue) {
var sValue = ARG_sValue |0;
var len = initLen |0;
switch (compGoto) {
case 0:
if (len & 0x80000000) {
const nCB = len & 0x80000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 1:
if (len & 0x40000000) {
const nCB = len & 0xc0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 2:
if (len & 0x20000000) {
const nCB = len & 0xe0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 3:
if (len & 0x10000000) {
const nCB = len & 0xf0000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 4:
if (len & 0x8000000) {
const nCB = len & 0xf8000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 5:
if (len & 0x4000000) {
const nCB = len & 0xfc000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 6:
if (len & 0x2000000) {
const nCB = len & 0xfe000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 7:
if (len & 0x1000000) {
const nCB = len & 0xff000000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 8:
if (len & 0x800000) {
const nCB = len & 0xff800000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 9:
if (len & 0x400000) {
const nCB = len & 0xffc00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 10:
if (len & 0x200000) {
const nCB = len & 0xffe00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 11:
if (len & 0x100000) {
const nCB = len & 0xfff00000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 12:
if (len & 0x80000) {
const nCB = len & 0xfff80000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 13:
if (len & 0x40000) {
const nCB = len & 0xfffc0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 14:
if (len & 0x20000) {
const nCB = len & 0xfffe0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 15:
if (len & 0x10000) {
const nCB = len & 0xffff0000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 16:
if (len & 0x8000) {
const nCB = len & 0xffff8000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 17:
if (len & 0x4000) {
const nCB = len & 0xffffc000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 18:
if (len & 0x2000) {
const nCB = len & 0xffffe000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 19:
if (len & 0x1000) {
const nCB = len & 0xfffff000;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 20:
if (len & 0x800) {
const nCB = len & 0xfffff800;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 21:
if (len & 0x400) {
const nCB = len & 0xfffffc00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 22:
if (len & 0x200) {
const nCB = len & 0xfffffe00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 23:
if (len & 0x100) {
const nCB = len & 0xffffff00;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 24:
if (len & 0x80) {
const nCB = len & 0xffffff80;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 25:
if (len & 0x40) {
const nCB = len & 0xffffffc0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 26:
if (len & 0x20) {
const nCB = len & 0xffffffe0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 27:
if (len & 0x10) {
const nCB = len & 0xfffffff0;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 28:
if (len & 0x8) {
const nCB = len & 0xfffffff8;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 29:
if (len & 0x4) {
const nCB = len & 0xfffffffc;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 30:
if (len & 0x2) {
const nCB = len & 0xfffffffe;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
case 31:
if (len & 0x1) {
const nCB = len & 0xffffffff;
len ^= (len ^ (nCB-1)) & ((array[nCB] <= sValue |0) - 1 >>>0);
}
}
// MODIFICATION: Instead of returning the index, this binary search
// instead returns whether something was found or not.
if (array[len|0] !== sValue) {
return true; // preserve the value at this index
} else {
return false; // eliminate the value at this index
}
};
}
为了证明速度的不同,让我们来看看一些JSPerfs。对于filtering an array of 16 elements,二进制搜索比indexOf快约17%,而filterArrayByAnotherArray比indexOf快约93%。对于filtering an array of 256 elements,二进制搜索比indexOf快大约291%,而filterArrayByAnotherArray比indexOf快大约353%。对于filtering an array of 4096 elements,二进制搜索比indexOf快大约2655%,而filterArrayByAnotherArray比indexOf快大约4627%。
答案 9 :(得分:2)
答案 10 :(得分:1)
您可以设置过滤器功能以迭代&#34;过滤器阵列&#34;。
var arr = [1, 2, 3 ,4 ,5, 6, 7];
var filter = [4, 5, 6];
var filtered = arr.filter(
function(val) {
for (var i = 0; i < filter.length; i++) {
if (val == filter[i]) {
return false;
}
}
return true;
}
);
答案 11 :(得分:1)
下面是一个例子
let firstArray=[1,2,3,4,5];
let secondArray=[2,3];
let filteredArray = firstArray.filter((a) => secondArray.indexOf(a)<0);
console.log(filteredArray); //above line gives [1,4,5]
答案 12 :(得分:1)
以下示例使用new Set()
创建一个只包含唯一元素的过滤数组:
具有原始数据类型的数组:string,number,boolean,null,undefined,symbol:
const a = [1, 2, 3, 4];
const b = [3, 4, 5];
const c = Array.from(new Set(a.concat(b)));
将对象作为项目的数组:
const a = [{id:1}, {id: 2}, {id: 3}, {id: 4}];
const b = [{id: 3}, {id: 4}, {id: 5}];
const stringifyObject = o => JSON.stringify(o);
const parseString = s => JSON.parse(s);
const c = Array.from(new Set(a.concat(b).map(stringifyObject)), parseString);
答案 13 :(得分:1)
您可以编写一个通用的filterByIndex()函数,并在TS中使用类型推断来节省使用回调函数的麻烦:
假设你想要使用[2,4]数组中指定的索引过滤你的数组[1,2,3,4]。
var filtered = [1,2,3,4,].filter(byIndex(element => element, [2,4]))
byIndex函数需要元素函数和数组,如下所示:
byIndex = (getter: (e:number) => number, arr: number[]) => (x: number) => {
var i = getter(x);
return arr.indexOf(i);
}
然后结果
filtered = [1,3]
答案 14 :(得分:1)
来自另一个数组的更灵活的过滤数组,其中包含对象属性
function filterFn(array, diffArray, prop, propDiff) {
diffArray = !propDiff ? diffArray : diffArray.map(d => d[propDiff])
this.fn = f => diffArray.indexOf(f) === -1
if (prop) {
return array.map(r => r[prop]).filter(this.fn)
} else {
return array.filter(this.fn)
}
}
//You can use it like this;
var arr = [];
for (var i = 0; i < 10; i++) {
var obj = {}
obj.index = i
obj.value = Math.pow(2, i)
arr.push(obj)
}
var arr2 = [1, 2, 3, 4, 5]
var sec = [{t:2}, {t:99}, {t:256}, {t:4096}]
var log = console.log.bind(console)
var filtered = filterFn(arr, sec, 'value', 't')
var filtered2 = filterFn(arr2, sec, null, 't')
log(filtered, filtered2)
答案 15 :(得分:1)
function arr(arr1,arr2){
function filt(value){
return arr2.indexOf(value) === -1;
}
return arr1.filter(filt)
}
document.getElementById("p").innerHTML = arr([1,2,3,4],[2,4])
<p id="p"></p>
答案 16 :(得分:1)
var arr1= [1,2,3,4];
var arr2=[2,4]
function fil(value){
return value !=arr2[0] && value != arr2[1]
}
document.getElementById("p").innerHTML= arr1.filter(fil)
&#13;
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p id="p"></p>
&#13;
答案 17 :(得分:1)
你可以使用过滤器,然后对过滤器函数使用减少过滤数组,当它找到匹配时检查并返回true,然后在返回(!)时反转。每个元素在数组中调用一次filter函数。您没有对帖子中函数中的任何元素进行比较。
var a1 = [1, 2, 3, 4],
a2 = [2, 3];
var filtered = a1.filter(function(x) {
return !a2.reduce(function(y, z) {
return x == y || x == z || y == true;
})
});
document.write(filtered);
&#13;
答案 18 :(得分:1)
button.titleEdgeInsets=UIEdgeInsetsMake(left,bottom,right,top)
功能的最佳说明是https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Array/filter
你应该简单地调整功能:
filter
在分配变量值之前,您无法访问变量值
答案 19 :(得分:0)
Jack Giffin的解决方案很棒,但不适用于数字大于2 ^ 32的数组。下面是重构的快速版本,可根据Jack的解决方案过滤阵列,但它适用于64位阵列。
const Math_clz32 = Math.clz32 || ((log, LN2) => x => 31 - log(x >>> 0) / LN2 | 0)(Math.log, Math.LN2);
const filterArrayByAnotherArray = (searchArray, filterArray) => {
searchArray.sort((a,b) => a > b);
filterArray.sort((a,b) => a > b);
let searchArrayLen = searchArray.length, filterArrayLen = filterArray.length;
let progressiveLinearComplexity = ((searchArrayLen<<1) + filterArrayLen)>>>0
let binarySearchComplexity = (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0;
let i = 0;
if (progressiveLinearComplexity < binarySearchComplexity) {
return searchArray.filter(currentValue => {
while (filterArray[i] < currentValue) i=i+1|0;
return filterArray[i] !== currentValue;
});
}
else return searchArray.filter(e => binarySearch(filterArray, e) === null);
}
const binarySearch = (sortedArray, elToFind) => {
let lowIndex = 0;
let highIndex = sortedArray.length - 1;
while (lowIndex <= highIndex) {
let midIndex = Math.floor((lowIndex + highIndex) / 2);
if (sortedArray[midIndex] == elToFind) return midIndex;
else if (sortedArray[midIndex] < elToFind) lowIndex = midIndex + 1;
else highIndex = midIndex - 1;
} return null;
}
答案 20 :(得分:0)
当数组中的项是对象时,您可以这样做。
想法是使用map函数在内部数组中找到只有键的数组
然后检查这些键的数组是否包含外部数组中的特定元素键。
const existsInBothArrays = array1.filter((element1) =>
array2.map((element2) => element2._searchKey).includes(element1._searchKey),
);