중복을 포함하거나 포함하지 않을 수 있는 매우 간단한 JavaScript 배열이 있습니다.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
중복을 제거하고 고유한 값을 새 배열에 넣어야 합니다.
내가 시도한 모든 코드를 가리킬 수 있지만 작동하지 않기 때문에 쓸모가 없다고 생각합니다. jQuery 솔루션도 수락합니다.
질문자 :kramden88
중복을 포함하거나 포함하지 않을 수 있는 매우 간단한 JavaScript 배열이 있습니다.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
중복을 제거하고 고유한 값을 새 배열에 넣어야 합니다.
내가 시도한 모든 코드를 가리킬 수 있지만 작동하지 않기 때문에 쓸모가 없다고 생각합니다. jQuery 솔루션도 수락합니다.
Set 생성자와 스프레드 구문 사용 :
uniq = [...new Set(array)];
uniqueArray = a.filter(function(item, pos) { return a.indexOf(item) == pos; })
기본적으로 배열을 반복하고 각 요소에 대해 배열에서 이 요소의 첫 번째 위치가 현재 위치와 같은지 확인합니다. 분명히, 이 두 위치는 중복 요소에 대해 다릅니다.
필터 콜백의 세 번째("이 배열") 매개변수를 사용하여 배열 변수의 폐쇄를 피할 수 있습니다.
uniqueArray = a.filter(function(item, pos, self) { return self.indexOf(item) == pos; })
간결하지만 이 알고리즘은 큰 배열(2차 시간)에 특히 효율적이지 않습니다.
function uniq(a) { var seen = {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seen[item] = true); }); }
이것은 일반적으로 수행되는 방법입니다. 아이디어는 각 요소를 해시 테이블에 배치한 다음 해당 요소의 존재를 즉시 확인하는 것입니다. 이것은 선형 시간을 제공하지만 적어도 두 가지 단점이 있습니다.
uniq([1,"1"])
[1]
만 반환합니다.uniq([{foo:1},{foo:2}])
[{foo:1}]
만 반환합니다.즉, 배열에 프리미티브만 포함되어 있고 유형에 관심이 없는 경우(예: 항상 숫자임) 이 솔루션이 최적입니다.
범용 솔루션은 두 가지 접근 방식을 결합합니다. 기본 솔루션에는 해시 조회를 사용하고 객체에는 선형 검색을 사용합니다.
function uniq(a) { var prims = {"boolean":{}, "number":{}, "string":{}}, objs = []; return a.filter(function(item) { var type = typeof item; if(type in prims) return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true); else return objs.indexOf(item) >= 0 ? false : objs.push(item); }); }
또 다른 옵션은 먼저 배열을 정렬한 다음 이전 요소와 동일한 각 요소를 제거하는 것입니다.
function uniq(a) { return a.sort().filter(function(item, pos, ary) { return !pos || item != ary[pos - 1]; }); }
sort
대해 동일하기 때문에 객체에서는 작동하지 않습니다. 또한 부작용으로 원래 배열을 자동으로 변경합니다. 좋지 않습니다! 그러나 입력이 이미 정렬된 경우 이 방법이 sort
을 제거하면 됩니다).
예를 들어, 다르지만 일부 속성을 공유하는 개체를 필터링하기 위해 단순한 평등 이외의 일부 기준에 따라 목록을 고유화하려는 경우가 있습니다. 이것은 콜백을 전달하여 우아하게 수행할 수 있습니다. 이 "키" 콜백은 각 요소에 적용되고 동일한 "키"를 가진 요소는 제거됩니다. key
가 프리미티브를 반환할 것으로 예상되기 때문에 해시 테이블은 여기에서 잘 작동합니다.
function uniqBy(a, key) { var seen = {}; return a.filter(function(item) { var k = key(item); return seen.hasOwnProperty(k) ? false : (seen[k] = true); }) }
특히 유용한 key()
는 JSON.stringify
로 물리적으로 다르지만 "모양은 동일"한 객체를 제거합니다.
a = [[1,2,3], [4,5,6], [1,2,3]] b = uniqBy(a, JSON.stringify) console.log(b) // [[1,2,3], [4,5,6]]
key
가 기본이 아닌 경우 선형 검색에 의존해야 합니다.
function uniqBy(a, key) { var index = []; return a.filter(function (item) { var k = key(item); return index.indexOf(k) >= 0 ? false : index.push(k); }); }
Set
사용할 수 있습니다.
function uniqBy(a, key) { let seen = new Set(); return a.filter(item => { let k = key(item); return seen.has(k) ? false : seen.add(k); }); }
또는 Map
:
function uniqBy(a, key) { return [ ...new Map( a.map(x => [key(x), x]) ).values() ] }
둘 다 기본이 아닌 키에서도 작동합니다.
키로 개체를 제거할 때 "동일한" 개체 중 첫 번째 개체 또는 마지막 개체를 유지하려고 할 수 있습니다.
Set
변형을 사용하여 Map
을 사용하여 마지막을 유지합니다.
function uniqByKeepFirst(a, key) { let seen = new Set(); return a.filter(item => { let k = key(item); return seen.has(k) ? false : seen.add(k); }); } function uniqByKeepLast(a, key) { return [ ...new Map( a.map(x => [key(x), x]) ).values() ] } // data = [ {a:1, u:1}, {a:2, u:2}, {a:3, u:3}, {a:4, u:1}, {a:5, u:2}, {a:6, u:3}, ]; console.log(uniqByKeepFirst(data, it => it.u)) console.log(uniqByKeepLast(data, it => it.u))
밑줄 과 Lo-Dash 는 모두 uniq
방법을 제공합니다. 그들의 알고리즘은 기본적으로 위의 첫 번째 스니펫과 유사하며 다음과 같이 요약됩니다.
var result = []; a.forEach(function(item) { if(result.indexOf(item) < 0) { result.push(item); } });
이것은 2차이지만 기본 indexOf
래핑, 키로 uniqify하는 기능( iteratee
), 이미 정렬된 배열에 대한 최적화와 같은 멋진 추가 기능이 있습니다.
jQuery를 사용 중이고 달러 없이는 아무것도 견딜 수 없다면 다음과 같이 진행됩니다.
$.uniqArray = function(a) { return $.grep(a, function(item, pos) { return $.inArray(item, a) === pos; }); }
이는 다시 첫 번째 스니펫의 변형입니다.
함수 호출은 JavaScript에서 비용이 많이 들기 때문에 위의 솔루션은 간결하지만 특히 효율적이지 않습니다. 최대 성능을 위해 filter
를 루프로 교체하고 다른 함수 호출을 제거하십시오.
function uniq_fast(a) { var seen = {}; var out = []; var len = a.length; var j = 0; for(var i = 0; i < len; i++) { var item = a[i]; if(seen[item] !== 1) { seen[item] = 1; out[j++] = item; } } return out; }
이 추악한 코드 덩어리는 위의 스니펫 #3과 동일 하지만 훨씬 더 빠릅니다 .
function uniq(a) { var seen = {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seen[item] = true); }); } function uniq_fast(a) { var seen = {}; var out = []; var len = a.length; var j = 0; for(var i = 0; i < len; i++) { var item = a[i]; if(seen[item] !== 1) { seen[item] = 1; out[j++] = item; } } return out; } ///// var r = [0,1,2,3,4,5,6,7,8,9], a = [], LEN = 1000, LOOPS = 1000; while(LEN--) a = a.concat(r); var d = new Date(); for(var i = 0; i < LOOPS; i++) uniq(a); document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS) var d = new Date(); for(var i = 0; i < LOOPS; i++) uniq_fast(a); document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)
ES6은 Set 객체를 제공하여 일을 훨씬 쉽게 만듭니다.
function uniq(a) { return Array.from(new Set(a)); }
또는
let uniq = a => [...new Set(a)];
파이썬과 달리 ES6 세트는 삽입 순서로 반복되므로 이 코드는 원래 배열의 순서를 유지합니다.
그러나 고유한 요소가 있는 배열이 필요한 경우 처음부터 세트를 사용하지 않는 이유는 무엇입니까?
"게으른" 제너레이터 기반 버전의 uniq
는 동일한 기반으로 구축할 수 있습니다.
function* uniqIter(a) { let seen = new Set(); for (let x of a) { if (!seen.has(x)) { seen.add(x); yield x; } } } // example: function* randomsBelow(limit) { while (1) yield Math.floor(Math.random() * limit); } // note that randomsBelow is endless count = 20; limit = 30; for (let r of uniqIter(randomsBelow(limit))) { console.log(r); if (--count === 0) break } // exercise for the reader: what happens if we set `limit` less than `count` and why
jQuery를 사용하여 빠르고 더러운:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; var uniqueNames = []; $.each(names, function(i, el){ if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el); });
for 루프 또는 jQuery로 모든 나쁜 예를 보는 데 지쳤습니다. Javascript는 오늘날 정렬, 매핑 및 축소와 같은 완벽한 도구를 제공합니다.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; var uniq = names.reduce(function(a,b){ if (a.indexOf(b) < 0 ) a.push(b); return a; },[]); console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ] // one liner return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);
더 빠른 방법이 있을 수 있지만 이 방법이 꽤 괜찮습니다.
var uniq = names.slice() // slice makes copy of array before sorting it .sort(function(a,b){ return a > b; }) .reduce(function(a,b){ if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop()) return a; },[]); // this empty array becomes the starting value for a // one liner return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);
ES6에는 모든 중복을 제거하는 것이 매우 쉽고 성능이 좋은 Sets and Spread가 있습니다.
var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
누군가가 고유한 이름의 수를 기준으로 결과를 정렬하는 방법에 대해 질문했습니다.
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'] var uniq = names .map((name) => { return {count: 1, name: name} }) .reduce((a, b) => { a[b.name] = (a[b.name] || 0) + b.count return a }, {}) var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b]) console.log(sorted)
바닐라 JS: 세트와 같은 객체를 사용하여 중복 제거
항상 객체에 넣은 다음 키를 통해 반복할 수 있습니다.
function remove_duplicates(arr) { var obj = {}; var ret_arr = []; for (var i = 0; i < arr.length; i++) { obj[arr[i]] = true; } for (var key in obj) { ret_arr.push(key); } return ret_arr; }
Vanilla JS: 이미 본 값을 추적하여 중복 제거(order-safe)
또는 주문 안전 버전의 경우 개체를 사용하여 이전에 본 모든 값을 저장하고 배열에 추가하기 전에 값을 확인합니다.
function remove_duplicates_safe(arr) { var seen = {}; var ret_arr = []; for (var i = 0; i < arr.length; i++) { if (!(arr[i] in seen)) { ret_arr.push(arr[i]); seen[arr[i]] = true; } } return ret_arr; }
ECMAScript 6: 새로운 Set 데이터 구조 사용(order-safe)
ECMAScript 6에는 모든 유형의 값을 저장할 수 Set
Set.values
는 삽입 순서로 요소를 반환합니다.
function remove_duplicates_es6(arr) { let s = new Set(arr); let it = s.values(); return Array.from(it); }
사용 예:
a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; b = remove_duplicates(a); // b: // ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"] c = remove_duplicates_safe(a); // c: // ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"] d = remove_duplicates_es6(a); // d: // ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
배열 필터와 indexOf 함수를 사용하는 한 줄 버전:
arr = arr.filter(function (value, index, array) { return array.indexOf(value) === index; });
배열을 조작하기 위한 다양한 기능이 있는 라이브러리입니다.
jQuery의 턱시도와 Backbone.js의 멜빵과 함께하는 것이 동점입니다.
_.uniq(array, [isSorted], [iterator])
별칭: 고유
===를 사용하여 객체 동등성을 테스트 하는 배열 의 중복 없는 버전을 생성합니다. 배열 이 정렬되어 있다는 것을 미리 알고 있다면 isSorted에 대해 true 를 전달하면 훨씬 빠른 알고리즘이 실행됩니다. 변환을 기반으로 고유한 항목을 계산하려면 반복기 함수를 전달하십시오.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; alert(_.uniq(names, false));
filter
메소드의 두 번째 - index - 매개변수를 사용하여 JavaScript에서 간단하게 수행할 수 있습니다.
var a = [2,3,4,5,5,4]; a.filter(function(value, index){ return a.indexOf(value) == index });
또는 짧은 손으로
a.filter((v,i) => a.indexOf(v) == i)
한 줄:
let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy']; let dup = [...new Set(names)]; console.log(dup);
다음과 같이
Array.filter()
var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana']; console.log('Actual Array: ' + actualArr); var filteredArr = actualArr.filter(function(item, index) { if (actualArr.indexOf(item) == index) return item; }); console.log('Filtered Array: ' + filteredArr);
이것은 ES6에서 더 짧게 만들 수 있습니다.
actualArr.filter((item,index,self) => self.indexOf(item)==index);
다음 Array.filter()
대한 좋은 설명입니다.
네이티브 자바스크립트 함수를 사용하여 배열에서 중복을 제거하는 가장 간결한 방법은 다음과 같은 시퀀스를 사용하는 것입니다.
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
다른 예제에서 본 것처럼 reduce 함수 내에는 slice
나 indexOf
가 필요하지 않습니다! 그래도 필터 기능과 함께 사용하는 것이 좋습니다.
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
이미 몇몇 브라우저에서 작동하는 또 다른 ES6(2015) 방법은 다음과 같습니다.
Array.from(new Set(vals))
또는 스프레드 연산자를 사용하는 경우:
[...new Set(vals)]
건배!
상위 답변의 복잡성은 O(n²)
이지만 객체를 해시로 사용하여 O(n)
만으로 수행할 수 있습니다.
function getDistinctArray(arr) { var dups = {}; return arr.filter(function(el) { var hash = el.valueOf(); var isDup = dups[hash]; dups[hash] = true; return !isDup; }); }
이것은 문자열, 숫자 및 날짜에 대해 작동합니다. 배열에 개체가 포함된 경우 위의 솔루션은 문자열로 강제 변환될 때 모두 "[object Object]"
(또는 이와 유사한 값) 값을 가지며 조회 값으로 적합하지 않기 때문에 작동하지 않습니다. 객체 자체에 플래그를 설정하여 객체에 대한 O(n)
구현을 얻을 수 있습니다.
function getDistinctObjArray(arr) { var distinctArr = arr.filter(function(el) { var isDup = el.inArray; el.inArray = true; return !isDup; }); distinctArr.forEach(function(el) { delete el.inArray; }); return distinctArr; }
2019 편집: 최신 버전의 JavaScript를 사용하면 이 문제를 훨씬 쉽게 해결할 수 있습니다. 배열에 개체, 문자열, 숫자 또는 기타 유형이 포함되어 있는지 여부에 관계없이 Set
을 사용하면 작동합니다.
function getDistinctArray(arr) { return [...new Set(arr)]; }
구현이 너무 간단하여 더 이상 함수를 정의할 필요가 없습니다.
내가 지금까지 만난 가장 간단한 것. 에스6에서.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"] var noDupe = Array.from(new Set(names))
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
솔루션 1
Array.prototype.unique = function() { var a = []; for (i = 0; i < this.length; i++) { var current = this[i]; if (a.indexOf(current) < 0) a.push(current); } return a; }
솔루션 2(세트 사용)
Array.prototype.unique = function() { return Array.from(new Set(this)); }
시험
var x=[1,2,3,3,2,1]; x.unique() //[1,2,3]
성능
Chrome에서 성능에 대해 두 가지 구현(Set 포함 및 제외)을 모두 테스트했을 때 Set이 있는 구현이 훨씬 더 빠르다는 것을 알았습니다!
Array.prototype.unique1 = function() { var a = []; for (i = 0; i < this.length; i++) { var current = this[i]; if (a.indexOf(current) < 0) a.push(current); } return a; } Array.prototype.unique2 = function() { return Array.from(new Set(this)); } var x=[]; for(var i=0;i<10000;i++){ x.push("x"+i);x.push("x"+(i+1)); } console.time("unique1"); console.log(x.unique1()); console.timeEnd("unique1"); console.time("unique2"); console.log(x.unique2()); console.timeEnd("unique2");
이것으로 가십시오:
var uniqueArray = duplicateArray.filter(function(elem, pos) { return duplicateArray.indexOf(elem) == pos; });
이제 uniqueArray에는 중복 항목이 없습니다.
ECMAScript 6(ECMAScript 2015라고도 함)에서 Set
을 사용하여 중복을 필터링할 수 있습니다. 그런 다음 스프레드 연산자를 사용하여 다시 배열로 변환할 수 있습니다.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"], unique = [...new Set(names)];
나는 다른 질문에서 속임수 제거에 대한 자세한 비교를 수행했지만 이것이 실제 장소라는 것을 알게되어 여기에서도 공유하고 싶었습니다.
나는 이것이 이것을 하는 가장 좋은 방법이라고 믿는다
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200], reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{})); console.log(reduced);
OK .. 비록 이것이 O(n)이고 다른 것들은 O(n^2)이지만 나는 이 감소/조회 테이블과 filter/indexOf 콤보 사이의 벤치마크 비교를 보고 싶었습니다. (저는 Jeetendras를 아주 멋진 구현으로 선택했습니다 . //stackoverflow.com/a/37441144/4543207 ). 0-9999 범위의 임의의 양의 정수로 채워진 100K 항목 배열을 준비하고 중복을 제거합니다. 나는 테스트를 10번 반복했고 결과의 평균은 성능면에서 일치하지 않음을 보여줍니다.
글쎄요 지금까지는 너무 좋습니다. 하지만 이번에는 ES6 스타일로 제대로 해보자. 너무 멋져보이네요..! 그러나 현재로서는 강력한 lut 솔루션에 대해 성능이 어떻게 될지는 미스터리입니다. 먼저 코드를 보고 벤치마킹합니다.
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200], reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()]; console.log(reduced);
헐 짧았어..! 근데 성능은..? 멋지네요... 필터/indexOf의 무거운 무게가 우리 어깨 위로 들어왔기 때문에 이제 10개의 연속 테스트에서 평균을 얻기 위해 범위 0..99999에서 양의 정수로 구성된 1M 무작위 항목 배열을 테스트할 수 있습니다. 이번에는 진짜 대결이라고 말할 수 있다. 결과를 직접 확인하세요 :)
var ranar = [], red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})), red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 10; for (var i = 0; i<count; i++){ ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("reduce & lut took: " + avg1 + "msec"); console.log("map & spread took: " + avg2 + "msec");
어떤걸 쓰시겠습니까..? 뭐 그렇게 빠르진 않은데...! 속지 마세요. 지도가 변위 상태입니다. 이제 보세요... 위의 모든 경우에서 크기가 n인 배열을 범위 < n의 숫자로 채웁니다. 내 말은 우리는 크기가 100인 배열이 있고 난수 0..9로 채워서 명확한 중복이 있고 "거의" 확실히 각 숫자에 중복이 있습니다. 크기 100의 배열을 난수 0..9999로 채우면 어떻습니까? 이제 집에서 플레이하는 맵을 봅시다. 이번에는 100K 항목의 배열이지만 난수 범위는 0..100M입니다. 결과를 평균하기 위해 100회 연속 테스트를 수행합니다. 좋아 내기를 보자..! <- 오타 없음
var ranar = [], red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})), red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 100; for (var i = 0; i<count; i++){ ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("reduce & lut took: " + avg1 + "msec"); console.log("map & spread took: " + avg2 + "msec");
이제 Map()의 화려한 컴백입니다..! 이제 속임수를 제거하고 싶을 때 더 나은 결정을 내릴 수 있습니다.
자, 이제 우리 모두 행복합니다. 그러나 주연은 항상 박수와 함께 마지막에 옵니다. 여러분 중 일부는 Set 객체가 무엇을 할 것인지 궁금해 할 것입니다. 이제 우리는 ES6에 열려 있고 Map이 이전 게임의 승자라는 것을 알고 있으므로 Map과 Set을 결승전으로 비교하겠습니다. 이번에는 전형적인 레알마드리드vs바르셀로나 경기... 아님? 누가 엘 클라시코의 승자가 될지 지켜봅시다 :)
var ranar = [], red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], red2 = a => Array.from(new Set(a)), avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 100; for (var i = 0; i<count; i++){ ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("map & spread took: " + avg1 + "msec"); console.log("set & A.from took: " + avg2 + "msec");
와..남자..! 음 예상외로 엘 클라시코가 전혀 아니었습니다. CA Osasuna에 대한 바르셀로나 FC와 비슷합니다 :))
다음은 나열된 jQuery 메서드보다 80% 이상 빠릅니다(아래 테스트 참조). 몇 년 전 비슷한 질문에 대한 답변입니다. 원래 제안한 사람을 만나면 크레딧을 게시하겠습니다. 순수한 JS.
var temp = {}; for (var i = 0; i < array.length; i++) temp[array[i]] = true; var r = []; for (var k in temp) r.push(k); return r;
내 테스트 사례 비교: http://jsperf.com/remove-duplicate-array-tests
다음은 질문에 대한 간단한 답변입니다.
var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"]; var uniqueNames = []; for(var i in names){ if(uniqueNames.indexOf(names[i]) === -1){ uniqueNames.push(names[i]); } }
간단하지만 효과적인 기술은 filter function(value, index){ return this.indexOf(value) == index }
filter
메서드를 사용하는 것입니다.
var data = [2,3,4,5,5,4]; var filter = function(value, index){ return this.indexOf(value) == index }; var filteredData = data.filter(filter, data ); document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') + '</pre>';
이 Fiddle 도 참조하십시오.
다음은 어디에서나(PhotoshopScript에서도) 코드를 이해하고 작업하는 데 매우 간단합니다. 확인해 봐!
var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"); peoplenames = unique(peoplenames); alert(peoplenames); function unique(array){ var len = array.length; for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++) if(array[j] == array[i]){ array.splice(j,1); j--; len--; } return array; } //*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
따라서 옵션은 다음과 같습니다.
let a = [11,22,11,22]; let b = [] b = [ ...new Set(a) ]; // b = [11, 22] b = Array.from( new Set(a)) // b = [11, 22] b = a.filter((val,i)=>{ return a.indexOf(val)==i }) // b = [11, 22]
특별한 라이브러리가 없는 간단한 방법은 다음과 같습니다.
name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; }) console.log("Original name list:"+name_list.length, name_list) console.log("\n Unique name list:"+get_uniq.length, get_uniq)
현재 답변(미래 지향적인 ES6 제외)보다 더 간단하고 간결한 솔루션이 되는 것 외에도 나는 이것을 테스트했고 훨씬 더 빨랐습니다.
var uniqueArray = dupeArray.filter(function(item, i, self){ return self.lastIndexOf(item) == i; });
한 가지 주의 사항: Array.lastIndexOf()가 IE9에 추가되었으므로 이보다 더 낮게 설정해야 하는 경우 다른 곳을 찾아야 합니다.
다음은 ES2015의 일반적이고 엄격한 기능적 접근 방식입니다.
// small, reusable auxiliary functions const apply = f => a => f(a); const flip = f => b => a => f(a) (b); const uncurry = f => (a, b) => f(a) (b); const push = x => xs => (xs.push(x), xs); const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); const some = f => xs => xs.some(apply(f)); // the actual de-duplicate function const uniqueBy = f => foldl( acc => x => some(f(x)) (acc) ? acc : push(x) (acc) ) ([]); // comparators const eq = y => x => x === y; // string equality case insensitive :D const seqCI = y => x => x.toLowerCase() === y.toLowerCase(); // mock data const xs = [1,2,3,1,2,3,4]; const ys = ["a", "b", "c", "A", "B", "C", "D"]; console.log( uniqueBy(eq) (xs) ); console.log( uniqueBy(seqCI) (ys) );
unqiueBy
에서 unique
쉽게 파생 Set
사용하여 더 빠른 구현을 사용할 수 있습니다.
const unqiue = uniqueBy(eq); // const unique = xs => Array.from(new Set(xs));
이 접근 방식의 이점:
uniqueBy는 루프가 있는 명령형 구현만큼 빠르지는 않지만 uniqueBy
앱에서 구체적인 성능 저하의 원인으로 uniqueBy
를 식별한 경우 최적화된 코드로 교체하세요. 즉, 기능적이고 선언적인 방식으로 코드를 먼저 작성하십시오. 이후 성능 문제가 발생한다면 문제의 원인이 되는 위치에서 코드를 최적화하십시오.
uniqueBy
는 몸 안에 숨겨진 돌연변이( push(x) (acc)
각 반복 후에 버리는 대신 누산기를 재사용합니다. 이것은 메모리 소비와 GC 압력을 줄입니다. 이 부작용이 함수 내부에 래핑되기 때문에 외부의 모든 것은 순수하게 유지됩니다.
for (i=0; i<originalArray.length; i++) { if (!newArray.includes(originalArray[i])) { newArray.push(originalArray[i]); } }
혹시라도 사용 중이시라면
D3.js
당신은 할 수 있습니다
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
$(document).ready(function() { var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"] var arr2=["cat","fish","mango","apple"] var uniquevalue=[]; var seconduniquevalue=[]; var finalarray=[]; $.each(arr1,function(key,value){ if($.inArray (value,uniquevalue) === -1) { uniquevalue.push(value) } }); $.each(arr2,function(key,value){ if($.inArray (value,seconduniquevalue) === -1) { seconduniquevalue.push(value) } }); $.each(uniquevalue,function(ikey,ivalue){ $.each(seconduniquevalue,function(ukey,uvalue){ if( ivalue == uvalue) { finalarray.push(ivalue); } }); }); alert(finalarray); });
다음 스크립트는 고유한 값만 포함하는 새 배열을 반환합니다. 문자열과 숫자에서 작동합니다. 바닐라 JS만 추가 라이브러리에 대한 요구 사항이 없습니다.
브라우저 지원:
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Basic support (Yes) 1.5 (1.8) 9 (Yes) (Yes)
https://jsfiddle.net/fzmcgcxv/3/
var duplicates = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl","Mike","Mike","Nancy","Carl"]; var unique = duplicates.filter(function(elem, pos) { return duplicates.indexOf(elem) == pos; }); alert(unique);
사용자 지정 비교기를 사용하기 위해 thg435의 훌륭한 답변을 약간 수정했습니다.
function contains(array, obj) { for (var i = 0; i < array.length; i++) { if (isEqual(array[i], obj)) return true; } return false; } //comparator function isEqual(obj1, obj2) { if (obj1.name == obj2.name) return true; return false; } function removeDuplicates(ary) { var arr = []; return ary.filter(function(x) { return !contains(arr, x) && arr.push(x); }); }
ES6 솔루션이 최고지만 다음 솔루션을 아무도 보여주지 않은 것에 대해 당황스럽습니다.
function removeDuplicates(arr){ o={} arr.forEach(function(e){ o[e]=true }) return Object.keys(o) }
여기서 기억해야 할 점은 객체에 고유 키가 있어야 한다는 것입니다. 우리는 모든 중복을 제거하기 위해 이것을 악용하고 있습니다. 나는 이것이 ES6 이전의 가장 빠른 솔루션이라고 생각했을 것입니다.
이것은 배열도 정렬한다는 것을 명심하십시오.
출처 : http:www.stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array
모든 브라우저에서 웹 페이지 캐싱을 어떻게 제어합니까? (0) | 2022.01.05 |
---|---|
Facebook은 브라우저의 통합 개발자 도구를 어떻게 비활성화합니까? (0) | 2022.01.05 |
Git 분리 헤드는 어떻게 수정합니까? (0) | 2022.01.05 |
JavaScript에서 값이 객체인지 확인 (0) | 2022.01.05 |
'input'의 알려진 속성이 아니므로 'ngModel'에 바인딩할 수 없습니다. (0) | 2022.01.05 |