하자 A
와 B
두 세트합니다. 나는 그들 사이 의 세트 차이 ( 또는 선호도에 따라) 를 계산하는 정말 빠르고 우아한 방법을 찾고 있습니다. 두 세트는 제목에서 알 수 있듯이 Javascript 배열로 저장 및 조작됩니다.A - B
A \B
노트:
- Gecko 특정 트릭은 괜찮습니다.
- 나는 기본 기능을 고수하는 것을 선호합니다 (하지만 더 빠르면 가벼운 라이브러리에 열려 있습니다)
- 나는 보았지만 테스트하지는 않았지만 JS.Set (이전 요점 참조)
편집 : 중복 요소가 포함 된 세트에 대한 주석을 발견했습니다. 내가 “set”이라고 말할 때 나는 (다른 것들 중에서) 중복 요소를 포함하지 않는다는 것을 의미하는 수학적 정의를 의미합니다.
답변
이것이 가장 효과적인지 모르겠지만 아마도 가장 짧은
A = [1, 2, 3, 4];
B = [1, 3, 4, 7];
diff = A.filter(function(x) { return B.indexOf(x) < 0 })
console.log(diff);
ES6로 업데이트 :
A = [1, 2, 3, 4];
B = [1, 3, 4, 7];
diff = A.filter(x => !B.includes(x) );
console.log(diff);
답변
글쎄, 7 년 후, ES6의 Set 객체를 사용하면 매우 쉽고 (하지만 여전히 파이썬 만큼 콤팩트하지는 않습니다 A - B
) indexOf
큰 배열 보다 빠르다고 합니다.
console.clear();
let a = new Set([1, 2, 3, 4]);
let b = new Set([5, 4, 3, 2]);
let a_minus_b = new Set([...a].filter(x => !b.has(x)));
let b_minus_a = new Set([...b].filter(x => !a.has(x)));
let a_intersect_b = new Set([...a].filter(x => b.has(x)));
console.log([...a_minus_b]) // {1}
console.log([...b_minus_a]) // {5}
console.log([...a_intersect_b]) // {2,3,4}
답변
객체를지도로 사용하여 user187291의 답변 에서 B
와 A
같이의 각 요소를 선형으로 스캔하지 않도록 할 수 있습니다 .
function setMinus(A, B) {
var map = {}, C = [];
for(var i = B.length; i--; )
map[B[i].toSource()] = null; // any other value would do
for(var i = A.length; i--; ) {
if(!map.hasOwnProperty(A[i].toSource()))
C.push(A[i]);
}
return C;
}
비표준 toSource()
방법 은 고유 한 속성 이름을 가져 오는 데 사용됩니다. 모든 요소에 이미 고유 한 문자열 표현이있는 경우 (숫자의 경우처럼) toSource()
호출 을 삭제하여 코드 속도를 높일 수 있습니다 .
답변
jQuery를 사용하는 가장 짧은 방법은 다음과 같습니다.
var A = [1, 2, 3, 4];
var B = [1, 3, 4, 7];
var diff = $(A).not(B);
console.log(diff.toArray());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
답변
배열 B를 해시 한 다음 B에없는 배열 A의 값을 유지합니다.
function getHash(array){
// Hash an array into a set of properties
//
// params:
// array - (array) (!nil) the array to hash
//
// return: (object)
// hash object with one property set to true for each value in the array
var hash = {};
for (var i=0; i<array.length; i++){
hash[ array[i] ] = true;
}
return hash;
}
function getDifference(a, b){
// compute the difference a\b
//
// params:
// a - (array) (!nil) first array as a set of values (no duplicates)
// b - (array) (!nil) second array as a set of values (no duplicates)
//
// return: (array)
// the set of values (no duplicates) in array a and not in b,
// listed in the same order as in array a.
var hash = getHash(b);
var diff = [];
for (var i=0; i<a.length; i++){
var value = a[i];
if ( !hash[value]){
diff.push(value);
}
}
return diff;
}
답변
Christoph의 아이디어를 통합하고 배열 및 객체 / 해시 ( each
및 친구)에 대한 몇 가지 비표준 반복 방법을 가정하면 총 약 20 줄의 선형 시간에서 차이, 결합 및 교차를 설정할 수 있습니다.
var setOPs = {
minusAB : function (a, b) {
var h = {};
b.each(function (v) { h[v] = true; });
return a.filter(function (v) { return !h.hasOwnProperty(v); });
},
unionAB : function (a, b) {
var h = {}, f = function (v) { h[v] = true; };
a.each(f);
b.each(f);
return myUtils.keys(h);
},
intersectAB : function (a, b) {
var h = {};
a.each(function (v) { h[v] = 1; });
b.each(function (v) { h[v] = (h[v] || 0) + 1; });
var fnSel = function (v, count) { return count > 1; };
var fnVal = function (v, c) { return v; };
return myUtils.select(h, fnSel, fnVal);
}
};
이것은 그 가정 each
및 filter
배열에 대해 정의하고 있으며, 우리는 두 개의 유틸리티 방법을 가지고 :
-
myUtils.keys(hash)
: 해시의 키가있는 배열을 반환합니다. -
myUtils.select(hash, fnSelector,
: true
fnEvaluator)fnEvaluator
를fnSelector
반환 하는 키 / 값 쌍을 호출 한 결과가있는 배열 을
반환합니다.
는 select()
느슨하게 커먼 리스프에서 영감을, 그리고 단지입니다 filter()
및 map()
하나에 굴렀다. (에서 정의하는 Object.prototype
것이 좋지만 그렇게하면 jQuery가 혼란스러워서 정적 유틸리티 메서드에 정착했습니다.)
성능 : 테스트
var a = [], b = [];
for (var i = 100000; i--; ) {
if (i % 2 !== 0) a.push(i);
if (i % 3 !== 0) b.push(i);
}
50,000 및 66,666 요소가있는 두 세트를 제공합니다. 이 값으로 AB는 약 75ms가 걸리고 결합과 교차는 각각 약 150ms가 걸립니다. (Mac Safari 4.0, 타이밍에 Javascript Date 사용)
20 줄의 코드에 대한 적절한 보상이라고 생각합니다.
답변
사용 Underscore.js를 (기능 JS위한 라이브러리)
>>> var foo = [1,2,3]
>>> var bar = [1,2,4]
>>> _.difference(foo, bar);
[4]