데이터 중복 제거에 대한 수요는 실제로 lodash와 같은 도구 라이브러리가 성숙하고 완전한 구현을 갖추고 있으며 프로덕션 환경에서 성숙하게 사용될 수 있다는 것입니다. 그러나 이것은 여러 아이디어를 사용하여 중복 제거가 어떻게 달성될 수 있는지 보기 위해 사고 확장의 관점에서 우리를 방해하지 않습니다. 이 기사에서는 주로 JavaScript 배열 중복 제거에 대한 몇 가지 아이디어를 공유합니다.
첫 번째는 기존의 이중 레이어 루프 비교 아이디어를 구현한 것입니다
function doubleLoopUniq(arr) { let result = []; for (let i = 0, len = arr.length, isExist; i < len; i++) { // 定义一个变量表示当前元素在 result 中是否存在。 isExist = false; for (let j = 0, rLen = result.length; j < rLen; j++) { if (result[j] === arr[i]) { // 依次对result 中的元素 和 原数组元素进行比对。 isExist = true; break; } } // 最后判断如果不存在,则将此元素插入result !isExist && result.push(arr[i]); } return result; }
JS에 내장된 indexOf를 중복 제거에 사용
function indexOfUniq(arr) { let result = []; for (let i = 0, len = arr.length; i < len; i++) { // 用indexOf 简化了二层循环的流程 if (result.indexOf(arr[i]) === -1) result.push(arr[i]); } return result; }
정렬 전후를 비교하여 중복 제거
function sortUniq(arr) { let result = [], last; // 这里解构是为了不对原数组产生副作用 [ ...arr ].sort().forEach(item => { if (item != last) { result.push(item); last = item; } }); return result; }
해시 테이블을 사용하여 중복 제거
function hashUniq(arr) { let hashTable = arr.reduce((result, curr, index, array) => { result[curr] = true; return result; }, {}) return Object.keys(hashTable).map(item => parseInt(item, 10)); }
ES6 코드 한 줄 설정 Deduplication
function toSetUniq(arr) { return Array.from(new Set(arr)); }
splice Deduplication (어레이 자체에서 직접 동작, 부작용 있음)
function inPlaceUniq(arr) { let idx = 0; while (idx < arr.length) { let compare = idx + 1; while (compare < arr.length) { if (arr[idx] == arr[compare]) { arr.splice(compare, 1); continue; } ++compare } ++idx; } return arr; }
마지막으로 간단하게 nodejs에서 테스트를 실행해 어느 것이 더 효율적인지 확인해보세요~
let data = []; for (var i = 0; i < 100000; i++) { data.push(Math.random()) } // 实现一个性能测试的装饰器 function performanceTest(fn, descript) { var a = new Date().getTime(); return function () { fn.apply(this, [].slice.call(arguments, 0)); console.log(descript, new Date().getTime() - a) } } performanceTest(hashUniq, "hashTable")(data) performanceTest(sortUniq, "sortUniq")(data) performanceTest(toSetUniq, "toSetUniq")(data) performanceTest(indexOfUniq, "indexOfUniq")(data) performanceTest(doubleLoopUniq, "doubleLoopUniq")(data) performanceTest(inPlaceUniq, "inPlaceUniq")(data)
결과는 다음과 같습니다.
hashTable 168ms sortUniq 332ms toSetUniq 80ms indexOfUniq 4280ms doubleLoopUniq 13303ms inPlaceUniq 9977ms
확장된 사고: 배열 내에 있는 경우 요소가 객체일 때 중복을 제거하는 방법은 무엇입니까?
참조형이기 때문에 deepEqual이 사용될 수밖에 없습니다. 이 아이디어는 이 문제에 대한 답은 될 수 있지만 필연적으로 충분히 효율적이지 않습니다.
위 테스트에서도 새로운 Set과 hashTable을 통한 중복제거가 가장 효율적이라는 것을 알 수 있습니다.
그래서 이 두 가지 방법을 기반으로 변환해야 한다는 것은 의심할 여지가 없습니다.
한편, 심층 비교로 인한 시간을 줄이기 위해 JSON.stringify를 사용하려고 합니다. 참조 유형을 기본 유형으로 변환합니다.
function collectionUniq(collection) { let hashTable = {}; collection.forEach(item => { hashTable[JSON.stringify(item)] = true; }) return Object.keys(hashTable).map(item => JSON.parse(item)) }
그러면 문제가 발생합니다. 우리 모두는 객체의 속성이 순서가 없다는 것을 알고 있습니다. 이것이 데이터의 경우라면 GG입니다.
let collection = [ { a: 1, b: 2, c: 3 }, { b: 2, c: 3, a: 1 } ]
toHash라는 아이디어가 있는데, 이 배열의 기본적인 중복 제거 후, 정확성을 보장하기 위해
먼저 JSON 문자열을 순회합니다 =>
charCodeAt()를 통해 각 문자열의 유니코드 인코딩을 가져옵니다. =>
함께 더해 총 개수를 구하고 마지막으로 쌍으로 비교하면 동일한 값을 갖는 것이 중복되므로 중복 제거 효과를 얻습니다.
function toHash(obj) { let power = 1; let res = 0; const string = JSON.stringify(obj, null, 2); for (let i = 0, l = string.length; i < l; i++) { switch (string[i]) { case '{': power *= 2 break case '}': power /= 2 break case ' ': case '\n': case '\r': case '\t': break default: res += string[i].charCodeAt(0) * power } } return res }
이것은 구현을 위한 기본 아이디어일 뿐이며, 해시 충돌 가능성을 줄이기 위해 일부 특수 문자의 가중치를 늘리거나 줄일 수 있습니다.
대박에 당첨될 확률보다 충돌 확률이 낮다는 것이 핵심입니다.
관련 권장 사항:
JavaScript 배열에서 여러 중복 제거 방법 공유
위 내용은 JavaScript 배열 중복 제거에 대한 여러 아이디어의 자세한 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!