[javascript] 배열에서 가장 많이 발생하는 요소 가져 오기

JavaScript 배열에서 가장 많이 발생하는 요소 ( mode ) 를 결정하는 우아한 방법을 찾고 있습니다.

예를 들어

['pear', 'apple', 'orange', 'apple']

'apple'요소는 가장 자주 하나이다.



답변

이것은 단지 모드입니다. 다음은 빠르고 최적화되지 않은 솔루션입니다. O (n)이어야합니다.

function mode(array)
{
    if(array.length == 0)
        return null;
    var modeMap = {};
    var maxEl = array[0], maxCount = 1;
    for(var i = 0; i < array.length; i++)
    {
        var el = array[i];
        if(modeMap[el] == null)
            modeMap[el] = 1;
        else
            modeMap[el]++;
        if(modeMap[el] > maxCount)
        {
            maxEl = el;
            maxCount = modeMap[el];
        }
    }
    return maxEl;
}


답변

2009 년부터 자바 스크립트에서 몇 가지 개발이있었습니다. 다른 옵션을 추가 할 것이라고 생각했습니다. 나는 그것이 실제로 문제가 될 때까지 효율성에 덜 관심을 가지고 있으므로 “우아한” 코드 (OP에 의해 규정 된대로)에 대한 나의 정의는 가독성을 선호합니다-물론 주관적입니다 …

function mode(arr){
    return arr.sort((a,b) =>
          arr.filter(v => v===a).length
        - arr.filter(v => v===b).length
    ).pop();
}

mode(['pear', 'apple', 'orange', 'apple']); // apple

이 특정 예에서 집합의 두 개 이상의 요소가 동일한 발생을 갖는 경우 배열에서 가장 최근에 나타나는 요소가 반환됩니다. 또한 원래 배열을 수정한다는 점을 지적 할 가치가 있습니다 Array.slice. 사전 에 전화로 원할 경우 방지 할 수 있습니다 .


편집 : 2015 년 이 발생 했기 때문에 일부 ES6 뚱뚱한 화살표로 예제를 업데이트했으며 예쁘게 보입니다 … 이전 버전과의 호환성이 걱정된다면 개정 내역 에서 찾을 수 있습니다 .


답변

George Jempty's알고리즘 계정에 대한 요청에 따라 수정 된 버전의 Matthew Flaschen's알고리즘을 제안합니다 .

function modeString(array) {
  if (array.length == 0) return null;

  var modeMap = {},
    maxEl = array[0],
    maxCount = 1;

  for (var i = 0; i < array.length; i++) {
    var el = array[i];

    if (modeMap[el] == null) modeMap[el] = 1;
    else modeMap[el]++;

    if (modeMap[el] > maxCount) {
      maxEl = el;
      maxCount = modeMap[el];
    } else if (modeMap[el] == maxCount) {
      maxEl += "&" + el;
      maxCount = modeMap[el];
    }
  }
  return maxEl;
}

이제 기호로 구분 된 모드 요소가있는 문자열을 반환합니다 &. 결과가 수신되면 해당 &요소에서 분할 할 수 있으며 모드를 사용할 수 있습니다 .

또 다른 옵션은 다음과 같이 모드 요소의 배열을 반환하는 것입니다.

function modeArray(array) {
  if (array.length == 0) return null;
  var modeMap = {},
    maxCount = 1,
    modes = [];

  for (var i = 0; i < array.length; i++) {
    var el = array[i];

    if (modeMap[el] == null) modeMap[el] = 1;
    else modeMap[el]++;

    if (modeMap[el] > maxCount) {
      modes = [el];
      maxCount = modeMap[el];
    } else if (modeMap[el] == maxCount) {
      modes.push(el);
      maxCount = modeMap[el];
    }
  }
  return modes;
}

위의 예에서 함수의 결과를 모드 배열로 처리 할 수 ​​있습니다.


답변

를 기반으로 밀사 의 ES6 + 응답, 당신은 사용할 수 있습니다 Array.prototype.reduce내가 아주 매끄러운 모습을 생각한다 (배열을 돌연변이 잠재적으로 분류 터지는와 반대) 귀하의 비교를 할 수 있습니다.

const mode = (myArray) =>
  myArray.reduce(
    (a,b,i,arr)=>
     (arr.filter(v=>v===a).length>=arr.filter(v=>v===b).length?a:b),
    null)

기본적으로 null로 설정되어 있습니다. null이 필터링 할 수있는 옵션 인 경우 항상 진실한 응답을 제공하지는 않습니다. 선택적인 두 번째 인수 일 수 있습니다.

다른 다양한 솔루션과 마찬가지로 단점은 ‘그리기 상태’를 처리하지 않는다는 것입니다. 그러나 이것은 여전히 ​​약간 더 관련된 감소 기능으로 달성 할 수 있습니다.


답변

a=['pear', 'apple', 'orange', 'apple'];
b={};
max='', maxi=0;
for(let k of a) {
  if(b[k]) b[k]++; else b[k]=1;
  if(maxi < b[k]) { max=k; maxi=b[k] }
}


답변

이 기능을 면접관을위한 퀴즈로 사용하면서 솔루션을 게시합니다.

const highest = arr => (arr || []).reduce( ( acc, el ) => {
  acc.k[el] = acc.k[el] ? acc.k[el] + 1 : 1
  acc.max = acc.max ? acc.max < acc.k[el] ? el : acc.max : el
  return acc
}, { k:{} }).max

const test = [0,1,2,3,4,2,3,1,0,3,2,2,2,3,3,2]
console.log(highest(test))


답변

여기에서 선언적 접근 방식을 시도합니다. 이 솔루션은 각 단어의 발생을 집계하는 개체를 만듭니다. 그런 다음 각 단어의 총 발생 횟수를 개체에서 찾은 가장 높은 값과 비교하여 개체를 배열로 필터링합니다.

const arr = ['hello', 'world', 'hello', 'again'];

const tally = (acc, x) => {

  if (! acc[x]) {
    acc[x] = 1;
    return acc;
  }

  acc[x] += 1;
  return acc;
};

const totals = arr.reduce(tally, {});

const keys = Object.keys(totals);

const values = keys.map(x => totals[x]);

const results = keys.filter(x => totals[x] === Math.max(...values));