[英]Check if two arrays have an object with the same property
这是我的目标:比较两个对象并找出是否有 1 个或多个共同点。 如果有 1 个或多个共同点,则返回true
否则(没有共同点)返回false
。
当前问题:我正在尝试将.some()
方法与来自 API 的 1 object 和本地的 1 object 一起使用,但有点困惑,为什么它不起作用……有什么想法吗? 它应该返回 true,因为 John 在两个对象中,但它返回 false
代码示例:在此示例中,它应返回true
,因为 John 是一个同时为 object 1 (result1) 和 object 2 (result 2) 的名称。 但是,它返回false
。
有谁能帮助我理解我在这里做错了什么?
var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'} ]; var result2 = [ {id:2, name:'John', email:'johnny@example.com'}, {id:4, name:'Bobby', email:'bobby@example.com'} ]; const hasSimilarElement = result1.some((item) => item.name === result2.name); console.log(hasSimilarElement);
您可以创建一个 function ,它需要一个 function f
用于查找,然后是两个 arrays xs
& ys
:
const checkBy = f => (xs, ys) => {
let [long, short] = xs.length > ys.length ? [xs, ys] : [ys, xs];
short = new Set(short.map(f));
return long.some(x => short.has(f(x)));
};
然后:
const checkByName = checkBy(x => x.name);
checkByName( [ {id: 1, name:'Sandra', type: 'user', username: 'sandra'}
, {id: 2, name: 'John', type: 'admin', username: 'johnny2'}
, {id: 3, name: 'Peter', type: 'user', username: 'pete'}
, {id: 4, name: 'Bobby', type: 'user', username: 'be_bob'}]
, [ {id: 2, name: 'John', email: 'johnny@example.com'}
, {id: 4, name: 'Bobby', email: 'bobby@example.com'}]);
//=> true
checkByName( [ {id: 1, name:'Sandra', type: 'user', username: 'sandra'}
, {id: 2, name: 'John', type: 'admin', username: 'johnny2'}
, {id: 3, name: 'Peter', type: 'user', username: 'pete'}
, {id: 4, name: 'Bobby', type: 'user', username: 'be_bob'}]
, [ {id: 2, name: 'xxxx', email: 'johnny@example.com'}
, {id: 4, name: 'yyyyy', email: 'bobby@example.com'}]);
//=> false
我将针对您的具体场景使用 customcommander 提出的技术,并且对于您可以从对象中提取唯一键作为原始类型的任何地方。 (这里的name
是字符串,这样就可以了。)
如果你需要更通用的东西,那么你可以提供一个 function 来判断两个元素是否相等并像这样使用它:
const overlap = (equal) => (xs, ys) => xs.some (x => ys.some (y => equal (x, y))) const result1 = [{id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'}] const result2 = [{id:2, name:'John', email:'johnny@example.com'}, {id:4, name:'Bobby', email:'bobby@example.com'}] console.log (overlap ((x, y) => x.name == y.name) (result1, result2))
在您可以生成唯一密钥的情况下,这效率较低,但它更通用。 您甚至可以将它用于两个 arrays,其中两个 arrays 具有不同结构的对象,例如传递(x, y) => x.id == y.primaryKey
。
从上面的评论...
“OP 需要在
result2
中find
result1
的item.name
值相等的项目,而不是直接比较result2
的不存在(因此undefined
)name
属性。”
或者按照3limin4t0r some
正确建议,可以再次将find
换成另一个。
const result1 = [ { id: 1, name: 'Sandra', type: 'user', username: 'sandra' }, { id: 2, name: 'John', type: 'admin', username: 'johnny2' }, { id: 3, name: 'Peter', type: 'user', username: 'pete' }, { id: 4, name: 'Bobby', type: 'user', username: 'be_bob' }, ]; const result2 = [ { id: 5, name: 'Lea', email: 'lea@example.com' }, { id: 2, name: 'John', email: 'johnny@example.com' }, ]; const result3 = [ { id: 5, name: 'Lea', email: 'lea@example.com' }, ]; const result4 = []; console.log( 'similar elements within `result1` and `result2`..?', result1.some(itemA => result2.some(itemB => itemB.name === itemA.name) ) ); console.log( 'similar elements within `result1` and `result3`..?', result1.some(itemA => result3.some(itemB => itemB.name === itemA.name) ) ); console.log( 'similar elements within `result1` and `result4`..?', result1.some(itemA => result4.some(itemB => itemB.name === itemA.name) ) );
.as-console-wrapper { min-height: 100%;important: top; 0; }
在下一次迭代中,其中一个原因可能会提出一个通用实现的 function,它允许自由选择要比较的属性名称。
实现 function 也提供some
some
提前退出以进行成功比较)。
在这里,我们将从较短的数组构建一个key
(属性名称)特定的值索引(单个迭代任务),其中,在迭代较长的数组时,我们会查找(无迭代)项目相似性的key
特定值。
function hasSimilarItemsByKey(key, arrA, arrB) { const [ // the shorter array will be the base // for a `key` specific value index. lookupArray, // the longer array will be iterated // and have its item `key` specific // values looked up at a value index. targetArray, ] = [ arrA, arrB, ].sort((a, b) => a.length - b.length); // create the object based value index // (from the shorter array). const valueIndex = lookupArray.reduce((lookup, item) => { const value = item[key]; lookup[value]??= value; return lookup; }, Object.create(null)); // A `prototype`-less object. Thus, // using the `in` operator is safe. return targetArray.some(item => item[key] in valueIndex); } const result1 = [ { id: 1, name: 'Sandra', type: 'user', username: 'sandra' }, { id: 2, name: 'John', type: 'admin', username: 'johnny2' }, { id: 3, name: 'Peter', type: 'user', username: 'pete' }, { id: 4, name: 'Bobby', type: 'user', username: 'be_bob' }, ]; const result2 = [ { id: 5, name: 'Lea', email: 'lea@example.com' }, { id: 2, name: 'John', email: 'johnny@example.com' }, ]; const result3 = [ // Attention, // A matching `id` and a non matching `name`. { id: 1, name: 'Lea', email: 'lea@example.com' }, ]; const result4 = []; console.log( 'similar elements within `result1` and `result2`\n', '...by `name`..?', hasSimilarItemsByKey('name', result1, result2), '...by `id`..?', hasSimilarItemsByKey('id', result1, result2), ); console.log( 'similar elements within `result1` and `result3`\n', '...by `name`..?', hasSimilarItemsByKey('name', result1, result3), '...by `id`..?', hasSimilarItemsByKey('id', result1, result3), ); console.log( 'similar elements within `result1` and `result4`\n', '...by `name`..?', hasSimilarItemsByKey('name', result1, result4), '...by `id`..?', hasSimilarItemsByKey('id', result1, result4), );
.as-console-wrapper { min-height: 100%;important: top; 0; }
Array.prototype.some() some() 方法测试数组中是否至少有一个元素通过提供的 function 实现的测试。
在您的示例中,您正在尝试比较 2 arrays 个对象。 你有 false 因为 result2.name 是未定义的,你可能需要指定特定元素的索引,例如 result2[0].name
如果您想将 2 arrays 与某些项进行比较,您还需要遍历 result2 项。 你可以使用这样的东西:
var result1 = [
{id:1, name:'Sandra', type:'user', username:'sandra'},
{id:2, name:'John', type:'admin', username:'johnny2'},
{id:3, name:'Peter', type:'user', username:'pete'},
{id:4, name:'Bobby', type:'user', username:'be_bob'}
];
var result2 = [
{id:2, name:'John', email:'johnny@example.com'},
{id:4, name:'Bobby', email:'bobby@example.com'}
];
const hasSimilarElement = result2.filter((item1) => !result1.some(item2 => item1.name === item2.name ));
console.log(hasSimilarElement);
您的代码失败的原因是您试图在 result1 数组到result2.name
的元素中找到name
的匹配项
但是, result2
也是一个Array
, Array 没有一个.name
恰好是所有元素.name
s 以某种方式与您正在搜索的元素相匹配 - 这不是它的工作原理
您需要同时迭代 Arrays 以查找匹配项
var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'} ]; var result2 = [ {id:2, name:'John', email:'johnny@example.com'}, {id:4, name:'Bobby', email:'bobby@example.com'} ]; const hasSimilarElement = result1.some((item) => result2.some(item2 => item.name === item2.name)); console.log(hasSimilarElement);
.as-console-wrapper { min-height: 100%;important: top; 0; }
然而,对于非常大的结果集,这是低效的 - 我不是“大 O 符号专家,但我相信这将是 O(n 2 ) - 你可能会比较result1.length
* result2.length
次
对于这个简单的案例,您可以只从两个结果中提取.name
,然后创建一个Set
...如果Set
大小小于组合结果.length
s,则表示存在重复
在这里,您将每个结果迭代一次 - 如果两个集合都有 1000 个元素,那就是 2,000 次迭代,而使用上面的朴素方法则为 1,000,000
var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'} ]; var result2 = [ {id:2, name:'John', email:'johnny@example.com'}, {id:4, name:'Bobby', email:'bobby@example.com'} ]; const hasSimilarElement = new Set([...result1, ...result2].map(({name}) => name)).size < result1.length + result2.length console.log(hasSimilarElement);
.as-console-wrapper { min-height: 100%;important: top; 0; }
但是,如果其中一个结果中有重复的名称,则存在缺陷,这将无法按预期工作
这里每个集合迭代两次 - 但是,给定 2 x 1,000 个长结果,4,000 次迭代仍然优于 1,000,000
var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'} ]; var result2 = [ {id:2, name:'John', email:'johnny@example.com'}, {id:4, name:'Bobby', email:'bobby@example.com'} ]; const set1 = new Set(result1.map(({name}) => name)); const set2 = new Set(result2.map(({name}) => name)); const both = new Set([...set1, ...set2]); const hasSimilarElement = both.size < set1.size + set2.size; console.log(hasSimilarElement);
.as-console-wrapper { min-height: 100%;important: top; 0; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.