다음과 같은 두 가지 결과 집합이 있습니다.
// 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에서 이와 같은 일을 할 수 있습니까?
답변
네이티브 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);
답변
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);
답변
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);
답변
@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"}
답변
import differenceBy from 'lodash/differenceBy'
const myDifferences = differenceBy(Result1, Result2, 'value')
이렇게하면 키 value
를 사용하여 비교하는 두 객체 배열 간의 차이가 반환 됩니다. 다른 키는 무시되므로 동일한 값을 가진 두 항목은 반환되지 않습니다.
이것은 lodash 의 일부입니다 .
답변
배열의 각 개체에 해당하는 고유 값으로 키를 사용하여 개체를 만든 다음 다른 개체에있는 키의 존재에 따라 각 배열을 필터링 할 수 있습니다. 작업의 복잡성을 줄입니다.
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);
답변
@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;
});
}