簡體   English   中英

檢查兩個arrays是否有一個具有相同屬性的object

[英]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 需要在result2find result1item.name值相等的項目,而不是直接比較result2的不存在(因此undefinedname屬性。”

或者按照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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM