如何查找JavaScript对象之间的公共属性
查找对象数组的公共/不同属性的最佳/最有效方法是什么 我需要确定存在于所有对象中且具有相同值(公共值)的属性集。 最好我也希望得到一个具有所有其他属性的数组(diff) 我已经寻找了一个高效的库/函数来实现它。但是什么也没找到。所以我自己试过了 考虑这个JS对象数组:如何查找JavaScript对象之间的公共属性,javascript,node.js,lodash,Javascript,Node.js,Lodash,查找对象数组的公共/不同属性的最佳/最有效方法是什么 我需要确定存在于所有对象中且具有相同值(公共值)的属性集。 最好我也希望得到一个具有所有其他属性的数组(diff) 我已经寻找了一个高效的库/函数来实现它。但是什么也没找到。所以我自己试过了 考虑这个JS对象数组: var objects = [{ id: '2j2w4f', color: 'red', height: 20, width: 40, owner: 'bob' }, { id: '
var objects = [{
id: '2j2w4f',
color: 'red',
height: 20,
width: 40,
owner: 'bob'
}, {
id: '2j2w3f',
color: 'red',
height: 20,
width: 41,
owner: 'bob'
}, {
id: '2j2w2f',
color: 'red',
height: 21,
}, {
id: '2j2w1f',
color: 'red',
height: 21,
width: 44
}];
我想将颜色
(值为红色
)确定为唯一的公共属性。
请注意,它们没有相同的属性集。例如,所有者
不是公共财产
这是我自己解决问题的尝试(使用lodash):
我也尝试过mapReduce方法,但那似乎更糟
我仍然认为这似乎有点复杂/耗时,我将在1000-10000个或更多对象上执行此操作,每个对象具有20-50个属性
有什么建议吗?编辑
对不起,我赶时间,没有足够的时间考虑。
事实上,没有必要这样做。我在想用二进制算法什么的
在这里,更新的代码没有排序。Console.time()给了我“3ms”。
我所做的与Bergi的解决方案类似,但是我没有收集所有明显的属性,而是搜索属性数量最少的元素。这减少了第二个循环的迭代次数
我的代码基于以下内容:
- 如果对象X具有选定对象没有的属性,则它不是公共属性李>
- 因此,选定对象具有所有公共属性+额外属性
- 选定对象的属性最少,因此验证的迭代次数较少
//返回给定数组的公共属性。
函数getCommonProps(对象)
{
//具有最低属性的对象的存储变量。
var lowest={obj:null,nProperties:1000};
//搜索具有最低属性的对象。O(n)。
for(对象中的变量j)
{
var_nProp=Object.key(objects[j]).length;
如果(_nProp<最低性能)
最低={obj:objects[j],n属性:_nProp};
}
//保存公共属性的var。
var-retArr=[];
//属性最少的对象应包含公共属性。
用于(最低obj中的var i)
如果(isCommonProp(objects,i))重新定位推送(i);
回程回程;
}
//检查该道具是否存在于给定数组的所有对象中。
功能isCommonProp(arr,prop)
{
用于(arr中的var i)
{
if(arr[i][prop]==未定义)
返回false;
}
返回true;
}
time('getCommonProps()_perf');
log(getCommonProps(对象));
timeEnd('getCommonProps()_perf');
在您的解决方案中,有两件事情看起来是错误的:
- 通过
var common=objects[0]代码>不复制对象,因此将损坏
对象
- 您可以检查obj中是否存在所有公共属性,还可以将obj的每个属性与当前公共属性进行比较。这似乎太过分了。起初没有意识到您也需要不同的
属性
function commonDifferentProperties(objects) {
var common = _.reduce(objects, function(acc, obj) {
for (var p in obj)
acc[p] = obj[p];
return acc;
}, {});
var different = _.reduce(objects, function(acc, obj) {
for (var p in common)
if (common[p] !== obj[p]) {
delete common[p];
acc.push(p);
}
return acc;
}, []);
return {
common: common,
different: different
};
}
以下是我使用vanilla JS所做的:
function commonDifferentProperties(objects) {
var common = JSON.parse(JSON.stringify(objects[0]));
var unmatchedProps = {};
for (var i = 1; i < objects.length; i++) {
for (var prop in objects[i]) {
checkProps(objects[i],common,prop);
}
for (var commProp in common) {
checkProps(common,objects[i],commProp);
}
}
console.log(common); // this is all the matched key/value pairs
console.log(unmatchedProps); // this is all the unmatched keys
return { common: common, different: unmatchedProps };
function checkProps(source, target, prop) {
if (source.hasOwnProperty(prop)) {
var val = source[prop];
if (!target.hasOwnProperty(prop) || target[prop] !== val) {
unmatchedProps[prop] = true; // note: you could extend this to store values, or number of times you found this key, or whatever
delete common[prop];
}
}
}
}
函数公共差异属性(对象){
var common=JSON.parse(JSON.stringify(objects[0]);
var unmatchedProps={};
对于(变量i=1;i
因此,我复制第一个对象,并使用它跟踪常见的关键点和值。然后我遍历数组中的所有其他对象,首先查看公共对象中的所有键/值,并与当前值进行比较,删除公共对象中缺少的属性(如果它们不在当前对象中),然后执行相反的操作以捕获当前对象中不在公共对象中的任何属性(或在当前值中,但具有错误的值)。以下是另一种使用和的方法:
你真的需要不同的属性吗?顺便说一句:修复了你对lodash不熟悉的问题,但在我看来,你是在迭代每个对象的属性,并将它们与第一个对象进行比较,这似乎是反向的。你应该只迭代第一个对象的属性,并将它们与其他对象进行比较对象(假设您只需要公共属性)。您还通过调用
delete common[key]来破坏对象[0]
;
。我不会从第一个对象中删除,而是从一个空对象开始并添加公共属性。这也将避免@LeonidBeschastny@MattBurland是的,我需要一个不同的。但我也可以只检查一下普通的,一旦我需要知道一个给定的属性是否是不常见的只有在t的情况下,你的方法才有效
function commonDifferentProperties(objects) {
var common = _.reduce(objects, function(acc, obj) {
for (var p in obj)
acc[p] = obj[p];
return acc;
}, {});
var different = _.reduce(objects, function(acc, obj) {
for (var p in common)
if (common[p] !== obj[p]) {
delete common[p];
acc.push(p);
}
return acc;
}, []);
return {
common: common,
different: different
};
}
function commonDifferentProperties(objects) {
var common = JSON.parse(JSON.stringify(objects[0]));
var unmatchedProps = {};
for (var i = 1; i < objects.length; i++) {
for (var prop in objects[i]) {
checkProps(objects[i],common,prop);
}
for (var commProp in common) {
checkProps(common,objects[i],commProp);
}
}
console.log(common); // this is all the matched key/value pairs
console.log(unmatchedProps); // this is all the unmatched keys
return { common: common, different: unmatchedProps };
function checkProps(source, target, prop) {
if (source.hasOwnProperty(prop)) {
var val = source[prop];
if (!target.hasOwnProperty(prop) || target[prop] !== val) {
unmatchedProps[prop] = true; // note: you could extend this to store values, or number of times you found this key, or whatever
delete common[prop];
}
}
}
}
_.reduce(objects, function(result, item) {
if (_.isEmpty(result)) {
return _.assign({}, item);
}
return _.transform(item, function(common, value, key) {
if (result[key] === value) {
common[key] = value;
}
}, {});
}, {});