วิธีรับความแตกต่างระหว่างอาร์เรย์ของอ็อบเจ็กต์สองอาร์เรย์ใน JavaScript


110

ฉันมีชุดผลลัพธ์สองชุดดังนี้:

// Result 1
[
    { value: "0", display: "Jamsheer" },
    { value: "1", display: "Muhammed" },
    { value: "2", display: "Ravi" },
    { value: "3", display: "Ajmal" },
    { value: "4", display: "Ryan" }
]

// Result 2
[
    { value: "0", display: "Jamsheer" },
    { value: "1", display: "Muhammed" },
    { value: "2", display: "Ravi" },
    { value: "3", display: "Ajmal" },
]

ผลลัพธ์สุดท้ายที่ฉันต้องการคือความแตกต่างระหว่างอาร์เรย์เหล่านี้ - ผลลัพธ์สุดท้ายควรเป็นดังนี้:

[{ value: "4", display: "Ryan" }]

เป็นไปได้ไหมที่จะทำสิ่งนี้ใน JavaScript?


ดังนั้นคุณต้องการอาร์เรย์ขององค์ประกอบทั้งหมดที่ไม่เกิดขึ้นในทั้งสองอาร์เรย์กรองด้วยค่าและการแสดงผล?
Cerbrus

ฉันต้องการความแตกต่างระหว่างอาร์เรย์ทั้งสอง ค่านี้จะปรากฏในอาร์เรย์ใด ๆ
BKM


2
ดูเหมือนว่าอาร์เรย์ดังที่แสดงเมื่อล็อกเข้ากับคอนโซล firebug ...
Mike C

2
ขออภัย แต่วัตถุ json ไม่ถูกต้อง ... คุณต้องเปลี่ยน = สำหรับ:
Walter Zalazar

คำตอบ:


145

ใช้เฉพาะ JS ดั้งเดิมสิ่งนี้จะได้ผล:

a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"},  { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]

function comparer(otherArray){
  return function(current){
    return otherArray.filter(function(other){
      return other.value == current.value && other.display == current.display
    }).length == 0;
  }
}

var onlyInA = a.filter(comparer(b));
var onlyInB = b.filter(comparer(a));

result = onlyInA.concat(onlyInB);

console.log(result);


1
วิธีนี้ใช้งานได้และอาจเป็นคำตอบโดยตรงที่ดีที่สุด แต่จะเป็นการดีหากเปลี่ยนเป็นสิ่งที่ยอมรับเพรดิเคตและสองรายการและส่งคืนความแตกต่างแบบสมมาตรของทั้งสองรายการโดยใช้เพรดิเคตอย่างเหมาะสม (คะแนนพิเศษหากมีประสิทธิภาพมากกว่าที่ต้องวิ่งผ่านการเปรียบเทียบ m * n ทั้งหมดสองครั้ง!)
Scott Sauyet

@ScottSauyet: ฉันไม่คุ้นเคยกับคำว่า"เพรดิเคต" (ไม่ใช่เจ้าของภาษาอังกฤษ) นั่นคือreturn a.value ===...คำตอบของคุณหรือไม่? (วิธีแก้ปัญหาที่ดีคือ +1) นอกเหนือจากการใช้งานArray.prototype.some()แล้วฉันไม่สามารถหาวิธีที่มีประสิทธิภาพ / สั้นกว่านี้ได้
Cerbrus

2
@Cerbrus: ใช่ เพรดิเคตคือฟังก์ชันที่ส่งคืนบูลีน ( trueหรือfalseค่า) ในกรณีนี้หากเราแยกแนวคิดเรื่องการทดสอบความเท่าเทียมออกจากส่วนที่เหลือของโค้ดโดยกำหนดให้ผู้ใช้ผ่านการตรวจสอบความเท่าเทียมกันเป็นฟังก์ชันเราสามารถทำ อัลกอริทึมทั่วไปที่ตรงไปตรงมา
Scott Sauyet

@ScottSauyet: ฉันใช้เวลาสักพักกว่าจะพบคำตอบนี้อีกครั้ง แต่ตอนนี้มันดีขึ้นแล้ว: D
Cerbrus

ES6 const Comparer = (otherArray) => (current) => otherArray.filter ((other) => other.value == current.value && other.display == current.display) .length == 0;
Shnigi

72

คุณสามารถใช้Array.prototype.filter()ร่วมกับArray.prototype.some().

นี่คือตัวอย่าง (สมมติว่าอาร์เรย์ของคุณถูกเก็บไว้ในตัวแปรresult1และresult2):

//Find values that are in result1 but not in result2
var uniqueResultOne = result1.filter(function(obj) {
    return !result2.some(function(obj2) {
        return obj.value == obj2.value;
    });
});

//Find values that are in result2 but not in result1
var uniqueResultTwo = result2.filter(function(obj) {
    return !result1.some(function(obj2) {
        return obj.value == obj2.value;
    });
});

//Combine the two arrays of unique entries
var result = uniqueResultOne.concat(uniqueResultTwo);

52

สำหรับผู้ที่ชอบโซลูชันแบบซับเดียวใน ES6 สิ่งนี้:

const arrayOne = [ 
  { value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer" },
  { value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed" },
  { value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi" },
  { value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal" },
  { value: "a63a6f77-c637-454e-abf2-dfb9b543af6c", display: "Ryan" },
];
          
const arrayTwo = [
  { value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer"},
  { value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed"},
  { value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi"},
  { value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal"},
];

const results = arrayOne.filter(({ value: id1 }) => !arrayTwo.some(({ value: id2 }) => id2 === id1));

console.log(results);


4
กรุณาอธิบาย!
Bruno Brito

ฉันชอบวิธีนี้ มันสร้างวัตถุชั่วคราวที่มีคุณสมบัติมูลค่าเท่านั้นดังนั้นให้มันเล็ก
deanwilliammills

16

ผมใช้วิธีวัตถุประสงค์ทั่วไปเล็กน้อยแม้จะคล้ายกันในความคิดที่จะเข้าใกล้ของทั้งสอง@Cerbrusและ@Kasper Moerch ฉันสร้างฟังก์ชันที่ยอมรับเพรดิเคตเพื่อตรวจสอบว่าวัตถุสองชิ้นเท่ากันหรือไม่ (ที่นี่เราไม่สนใจ $$hashKeyคุณสมบัติ แต่อาจเป็นอะไรก็ได้) และส่งคืนฟังก์ชันที่คำนวณความแตกต่างแบบสมมาตรของสองรายการตามเพรดิเคตนั้น:

a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"},  { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]

var makeSymmDiffFunc = (function() {
    var contains = function(pred, a, list) {
        var idx = -1, len = list.length;
        while (++idx < len) {if (pred(a, list[idx])) {return true;}}
        return false;
    };
    var complement = function(pred, a, b) {
        return a.filter(function(elem) {return !contains(pred, elem, b);});
    };
    return function(pred) {
        return function(a, b) {
            return complement(pred, a, b).concat(complement(pred, b, a));
        };
    };
}());

var myDiff = makeSymmDiffFunc(function(x, y) {
    return x.value === y.value && x.display === y.display;
});

var result = myDiff(a, b); //=>  {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}

มันมีข้อได้เปรียบเล็กน้อยมากกว่าแนวทางของ Cerebrus (เช่นเดียวกับแนวทางของ Kasper Moerch) ที่มันหนีออกมาก่อน หากพบรายการที่ตรงกันก็ไม่ต้องกังวลกับการตรวจสอบส่วนที่เหลือของรายการ ถ้าฉันมีcurryฟังก์ชั่นที่มีประโยชน์ฉันจะทำสิ่งนี้ให้แตกต่างออกไปเล็กน้อย แต่ก็ใช้ได้ดี

คำอธิบาย

ความคิดเห็นขอคำอธิบายโดยละเอียดสำหรับผู้เริ่มต้น นี่คือความพยายาม

เราส่งผ่านฟังก์ชันต่อไปนี้ไปที่makeSymmDiffFunc:

function(x, y) {
    return x.value === y.value && x.display === y.display;
}

ฟังก์ชันนี้เป็นวิธีที่เราตัดสินว่าวัตถุสองชิ้นมีค่าเท่ากัน เช่นเดียวกับฟังก์ชันทั้งหมดที่ส่งคืนtrueหรือfalseอาจเรียกว่า "ฟังก์ชันเพรดิเคต" แต่นั่นเป็นเพียงคำศัพท์เท่านั้น ประเด็นหลักคือmakeSymmDiffFuncถูกกำหนดค่าด้วยฟังก์ชันที่รับวัตถุสองชิ้นและส่งคืนtrueหากเราพิจารณาว่ามันเท่ากันfalseถ้าเราไม่ทำ

เมื่อใช้สิ่งนั้นmakeSymmDiffFunc(อ่าน "สร้างความแตกต่างแบบสมมาตร") จะส่งคืนฟังก์ชันใหม่ให้เรา:

        return function(a, b) {
            return complement(pred, a, b).concat(complement(pred, b, a));
        };

นี่คือฟังก์ชั่นที่เราจะใช้จริง เราส่งผ่านสองรายการและพบองค์ประกอบในรายการแรกไม่ใช่ในรายการที่สองจากนั้นองค์ประกอบในรายการที่สองไม่ใช่รายการแรกและรวมสองรายการนี้เข้าด้วยกัน

อย่างไรก็ตามเมื่อมองอีกครั้งฉันสามารถใช้คิวจากโค้ดของคุณได้อย่างแน่นอนและทำให้ฟังก์ชันหลักง่ายขึ้นเล็กน้อยโดยใช้some:

var makeSymmDiffFunc = (function() {
    var complement = function(pred, a, b) {
        return a.filter(function(x) {
            return !b.some(function(y) {return pred(x, y);});
        });
    };
    return function(pred) {
        return function(a, b) {
            return complement(pred, a, b).concat(complement(pred, b, a));
        };
    };
}());

complementใช้เพรดิเคตและส่งคืนองค์ประกอบของรายการแรกไม่ใช่ในรายการที่สอง วิธีนี้ง่ายกว่าพาสแรกของฉันที่มีcontainsฟังก์ชันแยกต่างหาก

สุดท้ายฟังก์ชันหลักจะรวมอยู่ในนิพจน์ฟังก์ชันที่เรียกใช้ทันที ( IIFE ) เพื่อป้องกันไม่ให้complementฟังก์ชันภายในอยู่นอกขอบเขตส่วนกลาง


อัปเดตไม่กี่ปีต่อมา

ตอนนี้ ES2015 เริ่มแพร่หลายไปแล้วฉันขอแนะนำเทคนิคเดียวกันนี้โดยมีแผ่นสำเร็จรูปน้อยกว่ามาก:

const diffBy = (pred) => (a, b) => a.filter(x => !b.some(y => pred(x, y)))
const makeSymmDiffFunc = (pred) => (a, b) => diffBy(pred)(a, b).concat(diffBy(pred)(b, a))

const myDiff = makeSymmDiffFunc((x, y) => x.value === y.value && x.display === y.display)

const result = myDiff(a, b)
//=>  {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}

1
คุณช่วยเพิ่มคำอธิบายเพิ่มเติมให้กับโค้ดของคุณได้ไหม ฉันไม่แน่ใจว่าผู้เริ่มต้นใน JavaScript จะเข้าใจวิธีการทำงานของ predicate-approach
kaspermoerch

1
@KasperMoerch: เพิ่มคำอธิบายยาว ๆ ฉันหวังว่าจะช่วยได้ (นอกจากนี้ยังทำให้ฉันตระหนักถึงการทำความสะอาดอย่างจริงจังที่รหัสนี้ควรมี)
Scott Sauyet

10
import differenceBy from 'lodash/differenceBy'

const myDifferences = differenceBy(Result1, Result2, 'value')

สิ่งนี้จะส่งคืนความแตกต่างระหว่างอาร์เรย์ของออบเจ็กต์สองอาร์เรย์โดยใช้คีย์valueเพื่อเปรียบเทียบ หมายเหตุสองสิ่งที่มีค่าเดียวกันจะไม่ถูกส่งกลับเนื่องจากคีย์อื่น ๆ จะถูกละเว้น

นี่คือส่วนหนึ่งของlodash


วัตถุ json ด้านบนไม่ถูกต้อง เมื่อลองวิธีนี้เปลี่ยน = สำหรับ:
Walter Zalazar

7

คุณสามารถสร้างออบเจ็กต์ที่มีคีย์เป็นค่าเฉพาะที่สอดคล้องกันสำหรับแต่ละอ็อบเจ็กต์ในอาร์เรย์จากนั้นกรองอาร์เรย์แต่ละรายการตามการมีอยู่ของคีย์ในอ็อบเจ็กต์ของอีกฝ่าย ช่วยลดความซับซ้อนของการดำเนินการ

ES6

let a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"},  { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
let b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];

let valuesA = a.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let valuesB = b.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let result = [...a.filter(({value}) => !valuesB[value]), ...b.filter(({value}) => !valuesA[value])];
console.log(result);

ES5

var a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"},  { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
var b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];

var valuesA = a.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var valuesB = b.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var result = a.filter(function(c){ return !valuesB[c.value]}).concat(b.filter(function(c){ return !valuesA[c.value]}));
console.log(result);


5

ฉันคิดว่าโซลูชัน @Cerbrus นั้นตรงจุด ฉันได้ใช้โซลูชันเดียวกัน แต่แตกรหัสซ้ำเป็นฟังก์ชันของตัวเอง (DRY)

 function filterByDifference(array1, array2, compareField) {
  var onlyInA = differenceInFirstArray(array1, array2, compareField);
  var onlyInb = differenceInFirstArray(array2, array1, compareField);
  return onlyInA.concat(onlyInb);
}

function differenceInFirstArray(array1, array2, compareField) {
  return array1.filter(function (current) {
    return array2.filter(function (current_b) {
        return current_b[compareField] === current[compareField];
      }).length == 0;
  });
}

4

ฉันพบวิธีแก้ปัญหานี้โดยใช้ตัวกรองและบางส่วน

resultFilter = (firstArray, secondArray) => {
  return firstArray.filter(firstArrayItem =>
    !secondArray.some(
      secondArrayItem => firstArrayItem._user === secondArrayItem._user
    )
  );
};


2

คุณสามารถทำ diff a บน b และ diff b บน a จากนั้นรวมผลลัพธ์ทั้งสอง

let a = [
    { value: "0", display: "Jamsheer" },
    { value: "1", display: "Muhammed" },
    { value: "2", display: "Ravi" },
    { value: "3", display: "Ajmal" },
    { value: "4", display: "Ryan" }
]

let b = [
    { value: "0", display: "Jamsheer" },
    { value: "1", display: "Muhammed" },
    { value: "2", display: "Ravi" },
    { value: "3", display: "Ajmal" }
]

// b diff a
let resultA = b.filter(elm => !a.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));

// a diff b
let resultB = a.filter(elm => !b.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));  

// show merge 
console.log([...resultA, ...resultB]);


1

คำตอบส่วนใหญ่ที่นี่ค่อนข้างซับซ้อน แต่ตรรกะที่อยู่เบื้องหลังสิ่งนี้ค่อนข้างง่ายหรือ

  1. ตรวจสอบว่าอาร์เรย์ใดยาวกว่าและระบุเป็นพารามิเตอร์แรก (หากความยาวเท่ากันลำดับพารามิเตอร์จะไม่สำคัญ)
  2. วนซ้ำอาร์เรย์ 1
  3. สำหรับองค์ประกอบการวนซ้ำปัจจุบันของ array1 ให้ตรวจสอบว่ามีอยู่ใน array2 หรือไม่
  4. หากไม่มีอยู่ให้เกินกว่า
  5. ดันไปที่อาร์เรย์ 'ความแตกต่าง'
const getArraysDifference = (longerArray, array2) => {
  const difference = [];

  longerArray.forEach(el1 => {      /*1*/
    el1IsPresentInArr2 = array2.some(el2 => el2.value === el1.value); /*2*/

    if (!el1IsPresentInArr2) { /*3*/
      difference.push(el1);    /*4*/
    }
  });

  return difference;
}

O (n ^ 2) ความซับซ้อน


1
บวก 1 สำหรับการรวมความซับซ้อน
delavago1999

0

ฉันได้สร้างความแตกต่างทั่วไปที่เปรียบเทียบวัตถุ 2 ชนิดและสามารถเรียกใช้ตัวจัดการการปรับเปลี่ยน gist.github.com/bortunac "diff.js" โดยใช้:

old_obj={a:1,b:2,c:[1,2]}
now_obj={a:2 , c:[1,3,5],d:55}

ดังนั้นคุณสมบัติ a ถูกแก้ไข b ถูกลบ c แก้ไขเพิ่ม d

var handler=function(type,pointer){
console.log(type,pointer,this.old.point(pointer)," | ",this.now.point(pointer)); 

}

ตอนนี้ใช้ like

df=new diff();
df.analize(now_obj,old_obj);
df.react(handler);

คอนโซลจะแสดง

mdf ["a"]  1 | 2 
mdf ["c", "1"]  2 | 3 
add ["c", "2"]  undefined | 5 
add ["d"]  undefined | 55 
del ["b"]  2 | undefined 

0

วิธีทั่วไปและง่ายที่สุด:

findObject(listOfObjects, objectToSearch) {
    let found = false, matchingKeys = 0;
    for(let object of listOfObjects) {
        found = false;
        matchingKeys = 0;
        for(let key of Object.keys(object)) {
            if(object[key]==objectToSearch[key]) matchingKeys++;
        }
        if(matchingKeys==Object.keys(object).length) {
            found = true;
            break;
        }
    }
    return found;
}

get_removed_list_of_objects(old_array, new_array) {
    // console.log('old:',old_array);
    // console.log('new:',new_array);
    let foundList = [];
    for(let object of old_array) {
        if(!this.findObject(new_array, object)) foundList.push(object);
    }
    return foundList;
}

get_added_list_of_objects(old_array, new_array) {
    let foundList = [];
    for(let object of new_array) {
        if(!this.findObject(old_array, object)) foundList.push(object);
    }
    return foundList;
}

0

ฉันชอบวัตถุแผนที่เมื่อพูดถึงอาร์เรย์ขนาดใหญ่

// create tow arrays
array1 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))
array2 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))

// calc diff with some function
console.time('diff with some');
results = array2.filter(({ value: id1 }) => array1.some(({ value: id2 }) => id2 === id1));
console.log('diff results ',results.length)
console.timeEnd('diff with some');

// calc diff with map object
console.time('diff with map');
array1Map = {};
for(const item1 of array1){
    array1Map[item1.value] = true;
}
results = array2.filter(({ value: id2 }) => array1Map[id2]);
console.log('map results ',results.length)
console.timeEnd('diff with map');


0

JavaScript มีแผนที่ซึ่งให้เวลาในการแทรกและค้นหา O (1) ดังนั้นจึงสามารถแก้ไขได้ใน O (n) (และไม่ใช่ O (n²) เหมือนคำตอบอื่น ๆ ทั้งหมด) ด้วยเหตุนี้จึงจำเป็นต้องสร้างคีย์ดั้งเดิม (สตริง / ตัวเลข) ที่ไม่ซ้ำกันสำหรับแต่ละออบเจ็กต์ สามารถทำได้JSON.stringifyแต่มีข้อผิดพลาดค่อนข้างมากเนื่องจากลำดับขององค์ประกอบอาจมีผลต่อความเท่าเทียมกัน:

 JSON.stringify({ a: 1, b: 2 }) !== JSON.stringify({ b: 2, a: 1 })

ดังนั้นฉันจะใช้ตัวคั่นที่ไม่ปรากฏในค่าใด ๆ และเขียนสตริงด้วยตนเอง:

const toHash = value => value.value + "@" + value.display;

จากนั้นแผนที่จะถูกสร้างขึ้น เมื่อองค์ประกอบมีอยู่แล้วในแผนที่องค์ประกอบนั้นจะถูกลบออกมิฉะนั้นจะถูกเพิ่มเข้าไป ดังนั้นจึงเหลือเพียงองค์ประกอบที่รวมเวลาคี่ (หมายถึงเพียงครั้งเดียว) สิ่งนี้จะใช้ได้ก็ต่อเมื่อองค์ประกอบไม่ซ้ำกันในแต่ละอาร์เรย์:

const entries = new Map();

for(const el of [...firstArray, ...secondArray]) {
  const key = toHash(el);
  if(entries.has(key)) {
    entries.delete(key);
  } else {
    entries.set(key, el);
  }
}

const result = [...entries.values()];


0

ฉันเจอคำถามนี้ในขณะที่ค้นหาวิธีเลือกรายการแรกในอาร์เรย์หนึ่งที่ไม่ตรงกับค่าใด ๆ ในอาร์เรย์อื่นและจัดการเพื่อจัดเรียงในที่สุดด้วย array.find () และ array.filter () เช่น นี้

var carList= ['mercedes', 'lamborghini', 'bmw', 'honda', 'chrysler'];
var declinedOptions = ['mercedes', 'lamborghini'];

const nextOption = carList.find(car=>{
    const duplicate = declinedOptions.filter(declined=> {
      return declined === car
    })
    console.log('duplicate:',duplicate) //should list out each declined option
    if(duplicate.length === 0){//if theres no duplicate, thats the nextOption
      return car
    }
})

console.log('nextOption:', nextOption);
//expected outputs
//duplicate: mercedes
//duplicate: lamborghini
//duplicate: []
//nextOption: bmw

หากคุณต้องการเรียกดูรายการที่อัปเดตต่อไปก่อนที่จะตรวจสอบข้ามสำหรับตัวเลือกที่ดีที่สุดถัดไปสิ่งนี้จะใช้ได้ดีพอ :)


0

นอกจากนี้ให้พูดอาร์เรย์อ็อบเจ็กต์สองตัวที่มีค่าต่างกัน key value

// Array Object 1
const arrayObjOne = [
    { userId: "1", display: "Jamsheer" },
    { userId: "2", display: "Muhammed" },
    { userId: "3", display: "Ravi" },
    { userId: "4", display: "Ajmal" },
    { userId: "5", display: "Ryan" }
]

// Array Object 2
const arrayObjTwo =[
    { empId: "1", display: "Jamsheer", designation:"Jr. Officer" },
    { empId: "2", display: "Muhammed", designation:"Jr. Officer" },
    { empId: "3", display: "Ravi", designation:"Sr. Officer" },
    { empId: "4", display: "Ajmal", designation:"Ast. Manager" },
]

คุณสามารถใช้filterในes5หรือnative jsเพื่อแทนที่วัตถุอาร์เรย์สองชิ้น

//Find data that are in arrayObjOne but not in arrayObjTwo
var uniqueResultArrayObjOne = arrayObjOne.filter(function(objOne) {
    return !arrayObjTwo.some(function(objTwo) {
        return objOne.userId == objTwo.empId;
    });
});

ในES6คุณสามารถใช้ฟังก์ชั่น Arrow กับการทำลายโครงสร้างของES6.

const ResultArrayObjOne = arrayObjOne.filter(({ userId: userId }) => !arrayObjTwo.some(({ empId: empId }) => empId === userId));

console.log(ResultArrayObjOne);

0

let obj1 =[
                 { id: 1, submenu_name: 'login' },
                 { id: 2, submenu_name: 'Profile',}, 
                 { id: 3, submenu_name: 'password',  },  
                 { id: 4, submenu_name: 'reset',}
               ] ;
 let obj2 =[
                 { id: 2}, 
                 { id: 3 },
               ] ;
               
// Need Similar obj 
const result1 = obj1.filter(function(o1){
 return obj2.some(function(o2){
    return o1.id == o2.id;          // id is unnique both array object
  });
});
 console.log(result1);



// Need differnt obj 
 const result2 = obj1.filter(function(o1){
 return !obj2.some(function(o2){    //  for diffrent we use NOT (!) befor obj2 here
    return o1.id == o2.id;          // id is unnique both array object
  });
});
 console.log(result2);


-3

หากคุณต้องการใช้ไลบรารีภายนอกคุณสามารถใช้ _.difference ใน underscore.js เพื่อบรรลุเป้าหมายนี้ _.difference ส่งคืนค่าจากอาร์เรย์ที่ไม่มีอยู่ในอาร์เรย์อื่น

_.difference([1,2,3,4,5][1,4,10])

==>[2,3,5]

12
สิ่งนี้ใช้ได้กับอาร์เรย์ที่มีค่าดั้งเดิมเท่านั้น หากอาร์เรย์มีรายการของวัตถุเช่นคำถามนี้จะใช้ไม่ได้เนื่องจากพยายามเปรียบเทียบการอ้างอิงแทนที่จะเป็นวัตถุซึ่งมักจะหมายความว่าทุกอย่างแตกต่างกัน
Ross Peoples

1
ขอบคุณรอสที่คุณช่วยฉันจากอาการปวดหัว ฉันกำลังจะรายงานข้อผิดพลาดเพื่อขีดเส้นใต้
Etienne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.