Programing

배열에서 고유하지 않은 모든 값 (예 : 중복 / 둘 이상의 발생)을 가져옵니다.

lottogame 2020. 2. 25. 22:02
반응형

배열에서 고유하지 않은 모든 값 (예 : 중복 / 둘 이상의 발생)을 가져옵니다.


중복 값이 ​​있는지 확인하려면 JavaScript 배열을 확인해야합니다. 가장 쉬운 방법은 무엇입니까? 중복 된 값이 무엇인지 찾아야합니다. 실제로 색인이나 중복 횟수가 필요하지 않습니다.

배열을 반복하고 일치하는 다른 모든 값을 확인할 수 있지만 더 쉬운 방법이 있어야합니다. 어떤 아이디어? 감사!

비슷한 질문 :


배열을 정렬 한 다음 실행하여 다음 (또는 이전) 인덱스가 현재와 같은지 확인할 수 있습니다. 정렬 알고리즘이 양호하다고 가정하면 O (n 2 ) 보다 작아야합니다 .

var arr = [9, 9, 111, 2, 3, 4, 4, 5, 7];
var sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
                                     // JS by default uses a crappy string compare.
                                     // (we use slice to clone the array so the
                                     // original array won't be modified)
var results = [];
for (var i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
        results.push(sorted_arr[i]);
    }
}

console.log(results);

중복의 함수로 반환하려는 경우. 이것은 비슷한 유형의 경우입니다.

참조 : https://stackoverflow.com/a/57532964/8119511


복제본을 구상하려면 다음과 같은 훌륭한 솔루션을 시도하십시오.

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

출처 : http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/


이것은 중복 스레드 (!)의 대답입니다.

이 항목을 작성할 때 2014-모든 예제는 for-loops 또는 jQuery입니다. Javascript에는 정렬, 매핑 및 축소와 같은 완벽한 도구가 있습니다.

중복 항목 찾기

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 duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)

console.log(duplicates) // [ 'Nancy' ]

보다 기능적인 구문 :

@ Dmytro-Laptin은 일부 코드 코드가 제거되었다고 지적했습니다. 이것은 동일한 코드의보다 컴팩트 한 버전입니다. 일부 ES6 트릭과 고차 함수 사용 :

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const count = names =>
  names.reduce((a, b) => ({ ...a,
    [b]: (a[b] || 0) + 1
  }), {}) // don't forget to initialize the accumulator

const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1)

console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))) // [ 'Nancy' ]


배열에서 중복 값 찾기

이것은 실제로 배열에서 중복 값을 찾는 가장 짧은 방법 중 하나 여야합니다. OP에서 특별히 요청한대로 중복을 제거하지는 않지만 찾습니다 .

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

정렬 또는 타사 프레임 워크가 필요하지 않습니다. 또한 수동 루프가 필요하지 않습니다. indexOf () (또는 더 명확하게하기 위해 : 엄격한 비교 연산자 )가 지원 하는 모든 값으로 작동 합니다.

의 때문에 것은 감소 ()같이 IndexOf () 는 적어도 IE 9이 필요합니다.


이 함수를 추가하거나 조정하여 Javascript의 Array 프로토 타입에 추가 할 수 있습니다.

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);

업데이트 : 다음은 최적화 된 결합 전략을 사용합니다. 해시 O (1) 조회 시간의 이점을 얻기 위해 기본 조회를 최적화합니다 (기본 요소 unique배열에서 실행 되는 것은 O (n)입니다). 객체 조회는 반복하면서 고유 ID로 객체에 태그를 지정하여 최적화되므로 중복 객체를 식별하는 것도 항목 당 O (1)이고 전체 목록에 대해 O (n)입니다. 유일한 예외는 고정 된 항목이지만 드물고 대체는 array 및 indexOf를 사용하여 제공됩니다.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

ES6 모음을 사용할 수있는 경우 훨씬 간단하고 훨씬 빠른 버전이 있습니다. (IE9 + 및 기타 브라우저의 경우 : https://github.com/Benvie/ES6-Harmony-Collections-Shim )

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}

var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})

이것은 당신이 원하는 것을 얻을 것입니다.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.

underscore.js 사용

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}

업데이트 : 짧은 원 라이너로 복제본을 얻습니다.

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

중복없이 배열을 얻으려면 단순히 조건을 반전하십시오.

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

나는 단순히 filter()아래의 오래된 대답에서 생각하지 않았다 .)


이 질문 에서 요청한 것처럼 중복 항목이 없는지 확인하는 것이면 다음 every()방법을 사용할 수 있습니다 .

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

참고 every()아래의 IE 8 작동하지 않습니다.


여기에 간단한 단일 라인 솔루션이 있습니다.

먼저 고유 한 요소를 검색하지 않고 Set을 사용하여 찾은 배열을 고유하게 만듭니다.

그래서 결국에는 중복 배열이 있습니다.

var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];

console.log([...new Set(
  array.filter((value, index, self) => self.indexOf(value) !== index))]
);


var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});

또는 배열의 프로토 타입 체인에 추가 될 때

//copy and paste: without error handling
Array.prototype.unique = 
   function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}

여기를 참조하십시오 : https://gist.github.com/1305056


3 개 이상의 배열에서 고유 한 값을 찾으십시오.

Array.prototype.unique = function () {
    var arr = this.sort(), i; // input must be sorted for this to work
    for( i=arr.length; i--; )
      arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item

    return arr;
}

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,9],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique = arr.concat(arr2, arr3).unique();

console.log(unique);  // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4]

오래된 브라우저의 경우 arrayIndexOf에 대한 polyfill 만 있습니다.

if (!Array.prototype.indexOf){
   Array.prototype.indexOf = function(elt /*, from*/){
     var len = this.length >>> 0;

     var from = Number(arguments[1]) || 0;
     from = (from < 0) ? Math.ceil(from) : Math.floor(from);
     if (from < 0)
        from += len;

     for (; from < len; from++){
        if (from in this && this[from] === elt)
           return from;
     }
     return -1;
  };
}

"inArray"를 사용한 jQuery 솔루션 :

if( $.inArray(this[i], arr) == -1 )

ES2015

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique;

// Combine all the arrays to a single one
unique = arr.concat(arr2, arr3);
// create a new (dirty) Array with only the unique items
unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' )
// Cleanup - remove duplicate & empty items items 
unique = [...new Set(unique)].filter(n => n);

console.log(unique);

'Array.prototype.indexOf'를 추가하는 대신


es6 객체 구조 제거를 통한 빠르고 우아한 방법

O (n) (배열에 대한 1 회 반복)으로 실행되며 2 번 이상 나타나는 값을 반복하지 않습니다

const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
  dup
} = arr.reduce(
  (acc, curr) => {
    acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
    if (acc.items[curr] === 2) acc.dup.push(curr)
    return acc
  }, {
    items: {},
    dup: []
  },
)

console.log(dup)
// ['hi', 'bye']


이것은 나의 제안이다 (ES6).

let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]

// b is now [1, 2, 4]

매우 가볍고 쉬운 방법은 다음과 같습니다.

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}

ES6 (또는 Babel 또는 Typescipt 사용)을 사용하면 다음을 수행 할 수 있습니다.

var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);

https://es6console.com/j58euhbt/


ES6 구문의 간단한 코드 (복제 된 정렬 된 배열 반환) :

let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};

사용하는 방법:

duplicates([1,2,3,10,10,2,3,3,10]);

다음 함수 (이미 언급 된 removeDuplicates 함수의 변형)는 입력 [ "test", "test2", "test2", 1, 1, 1, 2에 대해 test2,1,7,5를 반환하는 트릭을 수행하는 것으로 보입니다. , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

JavaScript 배열은 거의 모든 것을 담을 수 있기 때문에 대부분의 다른 언어보다 JavaScript에서이 문제가 익숙하지 않습니다. 정렬을 사용하는 솔루션은 적절한 정렬 기능을 제공해야 할 수도 있습니다. 아직 해당 경로를 시도하지 않았습니다.

이 특정 구현은 (적어도) 문자열과 숫자에 적용됩니다.

function findDuplicates(arr) {
    var i,
        len=arr.length,
        out=[],
        obj={};

    for (i=0;i<len;i++) {
        if (obj[arr[i]] != null) {
            if (!obj[arr[i]]) {
                out.push(arr[i]);
                obj[arr[i]] = 1;
            }
        } else {
            obj[arr[i]] = 0;            
        }
    }
    return out;
}

ES5 전용 (즉, IE8 이하의 경우 filter () polyfill이 필요함) :

var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];

arrayToFilter.
    sort().
    filter( function(me,i,arr){
       return (i===0) || ( me !== arr[i-1] );
    });

var arr = [2, 1, 2, 2, 4, 4, 2, 5];

function returnDuplicates(arr) {
  return arr.reduce(function(dupes, val, i) {
    if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
      dupes.push(val);
    }
    return dupes;
  }, []);
}

alert(returnDuplicates(arr));

이 함수 는 정렬 단계를 피하고 reduce () 메소드를 사용하여 중복이 존재하지 않는 경우 새 배열로 중복을 푸시합니다.


"includes"를 사용하여 요소가 이미 존재하는지 테스트

var arr = [1, 1, 4, 5, 5], darr = [], duplicates = [];

for(var i = 0; i < arr.length; i++){
  if(darr.includes(arr[i]) && !duplicates.includes(arr[i]))
    duplicates.push(arr[i])
  else
    darr.push(arr[i]);
}

console.log(duplicates);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>


ES6은 기본적으로 중복을 허용하지 않는 배열 인 Set 데이터 구조를 제공합니다. Set 데이터 구조를 사용하면 배열에서 중복을 찾을 수있는 매우 쉬운 방법이 있습니다 (하나의 루프 만 사용).

여기 내 코드가 있습니다

function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
  for (let i = 0; i< arr.length; i++) {
     var size = set.size;
     set.add(arr[i]);
     if (set.size === size) {
         duplicates.add(arr[i]);
     }
  }
 return duplicates;
}

방금 배열 필터를 사용하여이를 달성하는 간단한 방법을 찾았습니다.

    var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    
    // Filter 1: to find all duplicates elements
    var duplicates = list.filter(function(value,index,self) {
       return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
    });
    
    console.log(duplicates);


논리를 따르는 것이 더 쉽고 빠릅니다.

// @Param:data:Array that is the source 
// @Return : Array that have the duplicate entries
findDuplicates(data: Array<any>): Array<any> {
        return Array.from(new Set(data)).filter((value) => data.indexOf(value) !== data.lastIndexOf(value));
      }

장점 :

  1. 한 줄 : -P
  2. 모든 내장 데이터 구조로 효율성 향상
  3. 더 빠른

논리 설명 :

  1. 모든 중복 항목을 제거하도록 설정으로 변환
  2. 설정된 값을 반복
  3. 소스 배열에서 각 설정 값을 검사 할 때 "첫 번째 색인 값이 마지막 색인과 같지 않습니다"==> 조건을 확인한 다음 중복으로 유추됩니다.

참고 : map () 및 filter () 메서드는 효율적이고 빠릅니다.


위의 이론을 추가하십시오.

중복을 찾는 것은 비교 모델에서 O (n * log (n)의 하한을 갖습니다. 따라서 이론적으로는 먼저 정렬을 한 다음 목록을 순차적으로 제거하여 찾은 중복을 제거하는 것보다 낫습니다.

선형 (O (n)) 예상 시간으로 중복 항목을 찾으려면 목록의 각 요소를 해시 할 수 있습니다. 충돌이있는 경우 중복으로 제거 / 라벨하고 계속하십시오.


var input = ['a', 'b', 'a', 'c', 'c'],
    duplicates = [],
    i, j;
for (i = 0, j = input.length; i < j; i++) {
  if (duplicates.indexOf(input[i]) === -1 && input.indexOf(input[i], i+1) !== -1) {
    duplicates.push(input[i]);
  }
}

console.log(duplicates);

아래는 귀하가 요청한 것을 정확하게 달성하는 가장 쉽고 빠른 O (n) 방법이라고 생각합니다.

function getDuplicates( arr ) {
  var i, value;
  var all = {};
  var duplicates = [];

  for( i=0; i<arr.length; i++ ) {
    value = arr[i];
    if( all[value] ) {
      duplicates.push( value );
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
  }

  return duplicates;
}

또는 ES5 이상인 경우 :

function getDuplicates( arr ) {
  var all = {};
  return arr.reduce(function( duplicates, value ) {
    if( all[value] ) {
      duplicates.push(value);
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
    return duplicates;
  }, []);
}

@Nosredna의 블로그에서 빌린 @RaphaelMontanaro의 솔루션을 수정하면 다음은 배열에서 중복 요소를 식별하려는 경우 수행 할 수있는 작업입니다.

function identifyDuplicatesFromArray(arr) {
        var i;
        var len = arr.length;
        var obj = {};
        var duplicates = [];

        for (i = 0; i < len; i++) {

            if (!obj[arr[i]]) {

                obj[arr[i]] = {};

            }

            else
            {
                duplicates.push(arr[i]);
            }

        }
        return duplicates;
    }

우아한 솔루션 @Nosredna에 감사드립니다!


나는 대부분의 답변을 좋아하지 않았다.

왜? 너무 복잡하고 너무 많은 코드, 비효율적 인 코드 및 많은 사람들이 질문에 대답하지 않습니다. 이는 복제본을 찾고 중복이없는 배열을 제공하지 않는 것입니다.

다음 함수는 모든 중복을 반환합니다.

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++) 
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return out;
}  

대부분의 경우 모든 복제본을 반환하는 데 쓸모가 없지만 어떤 중복 값이 ​​존재하는지 알려주는 데는 유용하지 않습니다. 이 경우 고유 중복을 가진 배열을 반환합니다 ;-)

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++)
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return GetUnique(out);
}

function GetUnique(arr) {
  return $.grep(arr, function(elem, index) {
    return index == $.inArray(elem, arr);
  });
}

다른 사람이 똑같이 생각할 수도 있습니다.

참고 URL : https://stackoverflow.com/questions/840781/get-all-non-unique-values-ie-duplicate-more-than-one-occurrence-in-an-array



반응형