检查两个数组是否具有具有同一属性的对象

发布于 2025-01-23 07:17:38 字数 1242 浏览 0 评论 0 原文

这是我的目标:比较两个对象,并找出是否有1个或更多项目。如果有1个或更多共同点,请返回 true 否则(没有共同的项目),返回 false

当前问题:我尝试使用 .some()方法,其中1个来自API的对象和1个本地对象,但有些困惑,为什么它不起作用。 ..任何想法?它应该返回true,因为John都在两个对象中,但是它返回false false

代码示例:在此示例中,它应该返回 true ,因为John是两个都是对象的名称1(结果1)和对象2(结果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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

const hasSimilarElement = result1.some((item) => item.name === result2.name); 

console.log(hasSimilarElement);

Here's my goal: compare two objects and figure out if there is 1 or more items in common. If there are 1 or more in common, return true otherwise (no items in common), return false.

Current issues: I'm trying to use the .some() method with 1 object from an API and 1 object that's local, but a bit confused why it's not working...any ideas? It should return true since John is in both objects, but it returns false ????

Code example: in this example, it should return true because John is a name that is both object 1 (result1) and object 2 (result 2). However, it returns false.

Is anyone able to help me understand what I'm doing wrong here?

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

const hasSimilarElement = result1.some((item) => item.name === result2.name); 

console.log(hasSimilarElement);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦初启 2025-01-30 07:17:38

您可以创建一个函数,该函数将功能 f 用于查找,然后两个数组 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: '[email protected]'}
             , {id: 4, name: 'Bobby', email:  '[email protected]'}]);
//=> 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: '[email protected]'}
             , {id: 4, name: 'yyyyy', email:  '[email protected]'}]);
//=> false

You can create a function that takes a function f to use for the lookup then two 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)));
};

Then:

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: '[email protected]'}
             , {id: 4, name: 'Bobby', email:  '[email protected]'}]);
//=> 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: '[email protected]'}
             , {id: 4, name: 'yyyyy', email:  '[email protected]'}]);
//=> false
巴黎盛开的樱花 2025-01-30 07:17:38

我将使用CustomCommander提出的技术来解决您的确切情况,并且在任何地方,您都可以从对象中提取一个唯一的键作为原始类型。 (这里 name 是字符串,因此有效。)

如果您需要更通用的东西,则可以提供一个函数,该函数告诉两个元素是否相等并这样使用:

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:'[email protected]'}, {id:4, name:'Bobby', email:'[email protected]'}]

console .log (overlap ((x, y) => x .name == y .name) (result1, result2))

在您可以生成唯一键的情况下,这效率较低,但更通用。您甚至可以将其用于两个数组,其中两个数组具有具有不同结构的对象,例如(x,y)=> x .id == y .primarykey

I would use the technique proposed by customcommander for your exact scenario, and for anywhere you can extract a unique key from your objects as a primitive type. (Here names are strings, so that works.)

If you need something more generic, then you can supply a function that tells if two elements are equal and use it like this:

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:'[email protected]'}, {id:4, name:'Bobby', email:'[email protected]'}]

console .log (overlap ((x, y) => x .name == y .name) (result1, result2))

This is less efficient in those cases where you could generate a unique key, but it's more generic. You can even use it for two arrays where the two arrays have objects with different structures, passing for instance (x, y) => x .id == y .primaryKey.

只是在用心讲痛 2025-01-30 07:17:38

array.prototype.some()
一些()方法测试数组中的至少一个元素是否通过提供的函数实现的测试。

在您的示例中,您正在尝试比较2个对象。您的结果为false2.名称不确定,您可能需要指定特定元素的索引,例如结果2 [0]

。您可以这样使用以下方式:

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];    
const hasSimilarElement = result2.filter((item1) => !result1.some(item2 => item1.name === item2.name ));

console.log(hasSimilarElement);

Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function.

In your example you are trying to compare 2 arrays of objects. You have false as result2.name is undefined, you might need to specify the index of an particular element e.g. result2[0].name

If you'd like to compare 2 arrays with some you need to iterate through result2 items as well. You can use somehting like this:

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];    
const hasSimilarElement = result2.filter((item1) => !result1.some(item2 => item1.name === item2.name ));

console.log(hasSimilarElement);
千柳 2025-01-30 07:17:38

您的代码失败的原因是,您正在尝试在Result1数组的元素中找到 name result2.name

,但是 result2 也是一个 array ,数组没有 .name ,恰好是所有元素 .name s,以某种方式与一个匹配您正在寻找 - 这不是它的工作方式,

您需要迭代两个阵列才能寻找匹配

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

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(N 2 ) - 您可能会比较> result1.length * result.2.length

对于此简单情况,您可以从两个结果中提取 .name /code> ...如果 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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

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; }

The reason your code fails is that you are trying to find a match for a name in the elements of result1 Array to result2.name

However, result2 is also an Array, Array's do not have a .name that happens to be all of the elements .names that somehow matches the one you are searching for - that's not how it works

You need to iterate both Arrays to look for a match

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

const hasSimilarElement = result1.some((item) => result2.some(item2 => item.name === item2.name)); 

console.log(hasSimilarElement);
.as-console-wrapper { min-height: 100%!important; top: 0; }

However, for very large result sets this is inefficient - I'm no "big O notation expert, but I believe this would be O(n2) - you're potentially going to compare result1.length * result2.length times

For this simple case, you can extract just the .name from both results, and create a Set ... if the Set size is less than the combined result .lengths it means there's a duplicate

here, you'll iterate each result once each - if both sets have 1000 elements that's 2,000 iterations, compared to 1,000,000 using the naive method above

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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

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; }

However, there is a flawif there's a duplicate name within one of the results, this will not work as expected

Here each set is iterated twice - but, given 2 x 1,000 long results, 4,000 iterations is still better than 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:'[email protected]'},
        {id:4, name:'Bobby', email:'[email protected]'}
    ];

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; }

久隐师 2025-01-30 07:17:38

从上面的评论...

“ op需要 查找 具有等价 item.name result> result 1 的物品 result> result 2 而不是直接直接比较非现有的(因此未定义 name result 2 的属性。”

。可以交换 noreflow noreferrer“> 对于另一个 再次。

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: '[email protected]' },
  { id: 2, name: 'John', email: '[email protected]' },
];

const result3 = [
  { id: 5, name: 'Lea', email: '[email protected]' },
];
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 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: '[email protected]' },
  { id: 2, name: 'John', email: '[email protected]' },
];

const result3 = [
  // Attention,
  // A matching `id` and a non matching `name`.
  { id: 1, name: 'Lea', email: '[email protected]' },
];
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; }

From the above comment ...

"The OP needs to find an item with an equal item.name value of result1 within result2 instead of directly comparing a non existing (thus undefined) name property of result2."

Or as correctly suggested by 3limin4t0r one could swap find for another some again.

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: '[email protected]' },
  { id: 2, name: 'John', email: '[email protected]' },
];

const result3 = [
  { id: 5, name: 'Lea', email: '[email protected]' },
];
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; }

Within a next iteration one of cause could come up with a generically implemented function which allows the to be compared property name to be freely chosen.

Implementing a function also gives the opportunity to get rid of the two nested some iterations (though some of cause exits early for a successful comparison).

Here one would build from the shorter array a key (property name) specific value-index (a single iteration task), where, while iterating the longer array, one would look up (no iteration) the key specific value for item similarity.

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: '[email protected]' },
  { id: 2, name: 'John', email: '[email protected]' },
];

const result3 = [
  // Attention,
  // A matching `id` and a non matching `name`.
  { id: 1, name: 'Lea', email: '[email protected]' },
];
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; }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文