> 웹 프론트엔드 > JS 튜토리얼 > JavaScript 배열 중복 제거에 대한 여러 아이디어의 자세한 예

JavaScript 배열 중복 제거에 대한 여러 아이디어의 자세한 예

小云云
풀어 주다: 2018-02-08 16:14:00
원래의
1513명이 탐색했습니다.

데이터 중복 제거에 대한 수요는 실제로 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 배열에서 여러 중복 제거 방법 공유

PHP에서 배열 중복 제거를 위한 메서드 코드

JS에서 배열을 중복 제거하는 간단한 방법 분석

위 내용은 JavaScript 배열 중복 제거에 대한 여러 아이디어의 자세한 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿