用另一个对象数组过滤对象数组

Posted

技术标签:

【中文标题】用另一个对象数组过滤对象数组【英文标题】:Filter array of objects with another array of objects 【发布时间】:2015-09-09 09:45:27 【问题描述】:

这个问题与Jquery filter array of object with loop 类似,但这次我需要对一组对象进行过滤。

示例:

我有一个这样的对象数组:

myArray = [

    userid: "100", 
    projectid: "10",
    rowid: "0"
,

    userid: "101", 
    projectid: "11",
    rowid: "1",
    
    userid: "102", 
    projectid: "12",
    rowid: "2",
    
    userid: "103", 
    projectid: "13",
    rowid: "3"
,
    
    userid: "101", 
    projectid: "10",
    rowid: "4"

...]

我想用这样的数组过滤它:

myFilter = [

    userid: "101", 
    projectid: "11"
,

    userid: "102", 
    projectid: "12"
,

    userid: "103", 
    projectid: "11"
]

并返回这个(myFilter中的userid和projectid需要匹配myArray中的userid和projectid):

myArrayFiltered = [

    userid: "101", 
    projectid: "11",
    rowid: "1"
,

    userid: "102", 
    projectid: "12",
    rowid: "2"
]

我该怎么做?

【问题讨论】:

【参考方案1】:

您可以在这里使用几个数组方法 - filtersome。它们适用于所有最新的浏览器,并且有适用于旧版浏览器的 polyfill。

const myArray = [ userid: "100", projectid: "10", rowid: "0" ,  userid: "101", projectid: "11", rowid: "1",  userid: "102", projectid: "12", rowid: "2" ,  userid: "103", projectid: "13", rowid: "3" ,  userid: "101", projectid: "10", rowid: "4" ];
const myFilter = [ userid: "101", projectid: "11" ,  userid: "102", projectid: "12" ,  userid: "103",  projectid: "11"];

const myArrayFiltered = myArray.filter((el) => 
  return myFilter.some((f) => 
    return f.userid === el.userid && f.projectid === el.projectid;
  );
);

console.log(myArrayFiltered);

【讨论】:

太棒了!比使用 for 循环更好!简洁很多 嗨@Andy,我正在做同样的事情,只是改变not equal to !== 的一个条件,但这不适用于我的情况。那么有没有其他方法可以处理不等于条件?在这里查看我的实时示例:playcode.io/586682 根据您的喜好,您还可以将声明更简洁一点:myArray.filter(el => myFilter.some(f => f.userid === el.userid && f.projectid === el.projectid))【参考方案2】:

使用 Ecma 脚本 6。

const myArrayFiltered = myArray.filter( el => 
  return myfilter.some( f => 
    return f.userid === el.userid && f.projectid === el.projectid;
  );
);

功能:

const filterObjectArray = (arr, filterArr) => (
    arr.filter( el =>
        filterArr.some( f =>
            f.userid === el.userid && f.projectid === el.projectid
        )
    )
);

console.log(filterObjectArray(myArray, myFilter))

Link to example

【讨论】:

【参考方案3】:

响应上面的Andy 答案,我认为现在应该将其标记为答案。如果您正在寻找完全相反的行为,请使用带有否定的every,类似这样。

const result = masterData.filter(ad => 
             filterData.every(fd => fd.userid !== md.userid));

result 包含 all masterData except filterData

【讨论】:

【参考方案4】:
var filtered = [];

for(var arr in myArray)
   for(var filter in myFilter)
       if(myArray[arr].userid == myFilter[filter].userid && myArray[arr].projectid == myFilter[filter].projectid)
          filtered.push(myArray[arr].userid);
         
   

console.log(filtered);

【讨论】:

【参考方案5】:

基于@Renato 他的回答,但更短:

const myArray = [ userid: "100", projectid: "10", rowid: "0" , ...];
const myFilter = [ userid: "101", projectid: "11" , ...];

const myArrayFiltered = myArray.filter(array => myFilter.some(filter => filter.userid === array.userid && filter.projectid === array.projectid));

【讨论】:

【参考方案6】:

你需要循环你的第一个数组,并在这个循环中,在过滤器中再次循环。

如果 userid 和 projectid 相等,则可以将该行添加到过滤后的数组中:

myArray = [
    userid: "100",
    projectid: "10",
    rowid: "0"
, 
    userid: "101",
    projectid: "11",
    rowid: "1"
, 
    userid: "102",
    projectid: "12",
    rowid: "2"
, 
    userid: "103",
    projectid: "13",
    rowid: "3"
, 
    userid: "101",
    projectid: "10",
    rowid: "4"
];
myFilter = [
    userid: "101",
    projectid: "11"
, 
    userid: "102",
    projectid: "12"
, 
    userid: "103",
    projectid: "11"
];

function filterArray(array, filter) 
    var myArrayFiltered = [];
    for (var i = 0; i < array.length; i++) 
        for (var j = 0; j < filter.length; j++) 
            if (array[i].userid === filter[j].userid && array[i].projectid === filter[j].projectid) 
                myArrayFiltered.push(array[i]);
            
        
    
    return myArrayFiltered;

myArrayFiltered = filterArray(myArray, myFilter);
console.log(myArrayFiltered);

JSFIDDLE

【讨论】:

【参考方案7】:

此代码不仅会匹配 userid 和 projectid,还会匹配 myFilter[j] 的所有属性。

var filtered = myArray.filter(function(i)
    return myFilter.some(function(j)
        return !Object.keys(j).some(function(prop)
            return i[prop] != j[prop];
        );
    );
);

console.log(filtered);

所以你可以使用

myFilter = [
    
        projectid: "11"
    ,
    
        userid: "101"
    ,
    
        userid: "103",
        projectid: "13",
        rowid: "3"
    
];

会回来

[  userid: '101', projectid: '11', rowid: '1' ,
 userid: '103', projectid: '13', rowid: '3' ,
 userid: '101', projectid: '10', rowid: '4'  ]

Wich 表示所有带有

的元素
(projectid=="11") 
OR (userid=="101") 
OR ( (userid=="103") AND (projectid=="13") AND (rowid=="3") )

【讨论】:

【参考方案8】:

你可以使用jquery map,这会返回一个匹配数组:

var _filter=function(arr_data,arr_filter)
    return $.map( arr_data, function( n ) 
        for(var f in arr_filter)
            if(arr_filter[f].userid == n.userid && arr_filter[f].projectid == n.projectid)
                return n;
            
        
    );

var resp = _filter(myArray,myFilter);
console.log(resp);

【讨论】:

【参考方案9】:

如果需要这样的过滤器,我建议创建一个字典(对象),其键是属性的哈希值,它定义了一个匹配(在本例中为 userid 和 projectid),您需要迭代第一个字典( haystack)检查第二个字典(针)中是否有可用的密钥。 希望这会有所帮助。

【讨论】:

【参考方案10】:
var arr1 = [
     name:'r', type:"t1" ,
     name:'i', type:"t2" ,
     name:'n', type:"t1" 
];

var arr2 = [
     name:'r', type:"t1" ,
     name:'i', type:"t2" ,
     name:'n', type:"t3" ,
];

let output = arr1.filter(x => !arr2.find(y => (y.name == x.name && y.type == x.type)));

console.log(output);

// inverted

output = arr1.filter(x => !!arr2.find(y => (y.name == x.name && y.type == x.type)));

console.log(output);

【讨论】:

【参考方案11】:

如果你需要相同的否定

const masterData = [

    userid: "101",
    projectid: "11",
    rowid: "1"
,

    userid: "101",
    projectid: "18",
    rowid: "1"
,

    userid: "101",
    projectid: "19",
    rowid: "1"
,
    userid: "102",
    projectid: "12",
    rowid: "2"
, 
    userid: "109",
    projectid: "10",
    rowid: "4"
];
const filterData = [

    userid: "101",
    projectid: "11"
,

    userid: "102",
    projectid: "12"
,

    userid: "109",
    projectid: "10"

];




const myArrayFiltered = masterData.filter(array => filterData.every(filter => (!(filter.userid === array.userid && filter.projectid === array.projectid))));

             console.log(myArrayFiltered)

【讨论】:

以上是关于用另一个对象数组过滤对象数组的主要内容,如果未能解决你的问题,请参考以下文章

从数组中过滤对象,具有匹配两个值的差异

用另一个不同长度的数组更新对象数组

无法根据另一个对象数组过滤对象数组

如何根据另一个对象数组过滤一个对象数组?

Angular2使用管道基于对象数组过滤对象数组

如何在javascript中将对象数组过滤为另一个对象数组? [关闭]