webentwicklung-frage-antwort-db.com.de

Rufen Sie das Element mit dem höchsten Vorkommen in einem Array ab

Ich suche nach einer eleganten Methode, um festzustellen, welches Element in einem JavaScript-Array das höchste Vorkommen ( mode ) hat. 

Zum Beispiel in

['pear', 'Apple', 'orange', 'Apple']

das 'Apple'-Element ist das häufigste Element.

64
vise

Dies ist nur der Modus. Hier ist ein schnell, nicht optimiert Lösung. Es sollte O (n) sein.

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;
}
70

Es gibt einige Entwicklungen in Javascript seit 2009 - ich dachte, ich würde eine weitere Option hinzufügen. Ich mache mir weniger Sorgen um die Effizienz, bis es tatsächlich ein Problem ist. Meine Definition von "elegantem" Code (wie vom OP festgelegt) begünstigt die Lesbarkeit - was natürlich subjektiv ist ...

_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
_

In diesem Beispiel wird das Element zurückgegeben, das als letztes im Array angezeigt wird, wenn zwei oder mehr Elemente des Satzes dasselbe Vorkommen haben. Es ist auch erwähnenswert, dass Ihr ursprüngliches Array dadurch geändert wird. Dies kann verhindert werden, wenn Sie zuvor einen Array.slice -Aufruf ausführen.


Edit: hat das Beispiel mit einigen ES6 fetten Pfeilen aktualisiert, weil 2015 ist passiert und ich finde sie sehen hübsch aus ... Wenn Sie sich mit Abwärtskompatibilität befassen, finden Sie dies in der Änderungshistorie .

43
Emissary

Als George Jempty's-Anforderung, den Algorithmus für Gleichungen zu verwenden, schlage ich eine modifizierte Version des Matthew Flaschen's-Algorithmus vor.

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;
}

Dies gibt nun eine Zeichenfolge mit den Moduselementen, die durch ein '&'-Symbol begrenzt sind, zurück. Wenn das Ergebnis empfangen wird, kann es in diesem '&'-Element aufgeteilt werden, und Sie haben Ihre Modi. 

Eine andere Option wäre, ein Array von Moduselementen wie folgt zurückzugeben:

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;
}

Im obigen Beispiel können Sie dann das Ergebnis der Funktion als Array von Modi behandeln.

30
samandmoore
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] }
}
11
Thinker

Basierend auf Emissary s ES6 + Antwort, können Sie Array.prototype.reduce für Ihren Vergleich verwenden (im Gegensatz zum Sortieren, Poppen und möglicherweise Mutieren Ihres Arrays).

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

Ich setze standardmäßig auf null. Dies gibt nicht immer eine wahrheitsgemäße Antwort, wenn null eine mögliche Option ist, nach der Sie filtern. Möglicherweise ist dies ein optionales zweites Argument

Der Nachteil ist, wie bei verschiedenen anderen Lösungen, dass es nicht mit "Draw-Zuständen" umgeht, dies könnte jedoch mit einer etwas aufwendigeren Reduktionsfunktion erreicht werden.

8
davidsharp

Hier einen deklarativen Ansatz ausprobieren. Diese Lösung erstellt ein Objekt, um die Vorkommen jedes Words zusammenzufassen. Filtert das Objekt anschließend bis zu einem Array, indem es die Gesamtzahl der einzelnen Wörter mit dem höchsten Wert im Objekt vergleicht.

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));
3
Corey Clark

Hier ist meine Lösung für dieses Problem, aber mit Zahlen und der neuen 'Set'-Funktion. Es ist nicht sehr performant, aber ich hatte definitiv viel Spaß beim Schreiben und es unterstützt mehrere Maximalwerte.

const mode = (arr) => [...new Set(arr)]
  .map((value) => [value, arr.filter((v) => v === value).length])
  .sort((a,b) => a[1]-b[1])
  .reverse()
  .filter((value, i, a) => a.indexOf(value) === i)
  .filter((v, i, a) => v[1] === a[0][1])
  .map((v) => v[0])

mode([1,2,3,3]) // [3]
mode([1,1,1,1,2,2,2,2,3,3,3]) // [1,2]

Übrigens: Verwenden Sie dies nicht für die Produktion. Dies ist nur ein Beispiel dafür, wie Sie es nur mit ES6- und Array-Funktionen lösen können.

2
Anjuna5

Da ich diese Funktion als Quiz für die Interviewer verwende, poste ich meine Lösung:

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))
2
perusopersonale

Diese Lösung kann mehrere Elemente eines Arrays zurückgeben, wenn sie zur gleichen Zeit auftreten. Beispielsweise hat ein Array arr = [3,4,3,6,4] zwei Moduswerte, 3 und 6.

Hier ist die Lösung,

function find_mode(arr) {
    var max = 0;
    var maxarr = [];
    var counter = [];
    var maxarr = [];

    arr.forEach(function(){
       counter.Push(0);
    });

    for(var i = 0;i<arr.length;i++){
       for(var j=0;j<arr.length;j++){
            if(arr[i]==arr[j])counter[i]++; 
       }
    } 


    max=this.arrayMax(counter);   

    for(var i = 0;i<arr.length;i++){
         if(counter[i]==max)maxarr.Push(arr[i]);
    }

    var unique = maxarr.filter( this.onlyUnique );
    return unique;

  };


function arrayMax(arr) {
      var len = arr.length, max = -Infinity;
      while (len--) {
              if (arr[len] > max) {
              max = arr[len];
              }
      }
  return max;
 };

 function onlyUnique(value, index, self) {
       return self.indexOf(value) === index;
 }
2
Reza

Versuchen Sie es auch, dies gilt jedoch nicht für die Browserversion des Kontos.

function mode(arr){
var a = [],b = 0,occurrence;
    for(var i = 0; i < arr.length;i++){
    if(a[arr[i]] != undefined){
        a[arr[i]]++;
    }else{
        a[arr[i]] = 1;
    }
    }
    for(var key in a){
    if(a[key] > b){
        b = a[key];
        occurrence = key;
    }
    }
return occurrence;
}
alert(mode(['segunda','terça','terca','segunda','terça','segunda']));

Bitte beachten Sie, dass diese Funktion das letzte Vorkommen im Array zurückgibt wenn 2 oder mehr Einträge gleich oft erscheinen!

1
Marcelo
function mode(arr){
  return arr.reduce(function(counts,key){
    var curCount = (counts[key+''] || 0) + 1;
    counts[key+''] = curCount;
    if (curCount > counts.max) { counts.max = curCount; counts.mode = key; }
    return counts;
  }, {max:0, mode: null}).mode
}
1
Jonah

Zeit für eine andere Lösung:

function getMaxOccurrence(arr) {
    var o = {}, maxCount = 0, maxValue, m;
    for (var i=0, iLen=arr.length; i<iLen; i++) {
        m = arr[i];

        if (!o.hasOwnProperty(m)) {
            o[m] = 0;
        }
        ++o[m];

        if (o[m] > maxCount) {
            maxCount = o[m];
            maxValue = m;
        }
    }
    return maxValue;
}

Wenn es auf die Kürze ankommt (ist es nicht so), dann:

function getMaxOccurrence(a) {
    var o = {}, mC = 0, mV, m;
    for (var i=0, iL=a.length; i<iL; i++) {
        m = a[i];
        o.hasOwnProperty(m)? ++o[m] : o[m] = 1;
        if (o[m] > mC) mC = o[m], mV = m;
    }
    return mV;
}

Wenn nicht vorhandene Member vermieden werden sollen (z. B. Array mit geringer Dichte), ist ein zusätzlicher hasOwnProperty -Test erforderlich:

function getMaxOccurrence(a) {
    var o = {}, mC = 0, mV, m;
    for (var i=0, iL=a.length; i<iL; i++) {
        if (a.hasOwnProperty(i)) {
            m = a[i];
            o.hasOwnProperty(m)? ++o[m] : o[m] = 1;
            if (o[m] > mC) mC = o[m], mV = m;
        }
    }
    return mV;
}

getMaxOccurrence([,,,,,1,1]); // 1

Andere Antworten hier geben undefined zurück.

1
RobG
var mode = 0;
var c = 0;
var num = new Array();
var value = 0;
var greatest = 0;
var ct = 0;

Hinweis: ct ist die Länge des Arrays.

function getMode()
{
    for (var i = 0; i < ct; i++)
    {
        value = num[i];
        if (i != ct)
        {
            while (value == num[i + 1])
            {
                c = c + 1;
                i = i + 1;
            }
        }
        if (c > greatest)
        {
            greatest = c;
            mode = value;
        }
        c = 0;
    }
}
1

Hier ist meine Lösung: -

function frequent(number){
    var count = 0;
    var sortedNumber = number.sort();
    var start = number[0], item;
    for(var i = 0 ;  i < sortedNumber.length; i++){
      if(start === sortedNumber[i] || sortedNumber[i] === sortedNumber[i+1]){
         item = sortedNumber[i]
      }
    }
    return item
  
}

   console.log( frequent(['pear', 'Apple', 'orange', 'Apple']))

1
Meheret
function mode(array){
    var set = Array.from(new Set(array));
    var counts = set.map(a=>array.filter(b=>b==a).length);
    var indices = counts.map((a,b)=>Math.max(...counts)===a?b:0).filter(b=>b!==0);
    var mode = indices.map(a=>set[a]);
    return mode;
}
0
ido klein
var cats = ['Tom','Fluffy','Tom','Bella','Chloe','Tom','Chloe'];
var counts = {};
var compare = 0;
var mostFrequent;
(function(array){
   for(var i = 0, len = array.length; i < len; i++){
       var Word = array[i];

       if(counts[Word] === undefined){
           counts[Word] = 1;
       }else{
           counts[Word] = counts[Word] + 1;
       }
       if(counts[Word] > compare){
             compare = counts[Word];
             mostFrequent = cats[i];
       }
    }
  return mostFrequent;
})(cats);
0
Rubin bhandari
const mode = (str) => {
  return str
    .split(' ')
    .reduce((data, key) => {
      let counter = data.map[key] + 1 || 1
      data.map[key] = counter

      if (counter > data.counter) {
        data.counter = counter
        data.mode = key
      }

      return data
    }, {
      counter: 0,
      mode: null,
      map: {}
    })
    .mode
}

console.log(mode('the t-rex is the greatest of them all'))
0
Pablo

Hier ist die moderne Version, die integrierte Karten verwendet (sodass sie nicht nur in Dinge konvertiert werden kann, die in eindeutige Zeichenfolgen umgewandelt werden können):

'use strict';

const histogram = iterable => {
    const result = new Map();

    for (const x of iterable) {
        result.set(x, (result.get(x) || 0) + 1);
    }

    return result;
};

const mostCommon = iterable => {
    let maxCount = 0;
    let maxKey;

    for (const [key, count] of histogram(iterable)) {
        if (count > maxCount) {
            maxCount = count;
            maxKey = key;
        }
    }

    return maxKey;
};

console.log(mostCommon(['pear', 'Apple', 'orange', 'Apple']));

0
Ry-

Sie können dies versuchen:

 // using splice()   
 // get the element with the highest occurence in an array
    function mc(a) {
      var us = [], l;
      // find all the unique elements in the array
      a.forEach(function (v) {
        if (us.indexOf(v) === -1) {
          us.Push(v);
        }
      });
      l = us.length;
      while (true) {
        for (var i = 0; i < l; i ++) {
          if (a.indexOf(us[i]) === -1) {
            continue;
          } else if (a.indexOf(us[i]) != -1 && a.length > 1) {
            // just delete it once at a time
            a.splice(a.indexOf(us[i]), 1);
          } else {
            // default to last one
            return a[0];
          }
        }
      }
    }

// using string.match method
function su(a) {
    var s = a.join(),
            uelms = [],
            r = {},
            l,
            i,
            m;

    a.forEach(function (v) {
        if (uelms.indexOf(v) === -1) {
            uelms.Push(v);
        }
    });

    l = uelms.length;

    // use match to calculate occurance times
    for (i = 0; i < l; i ++) {
        r[uelms[i]] = s.match(new RegExp(uelms[i], 'g')).length;
    }

    m = uelms[0];
    for (var p in r) {
        if (r[p] > r[m]) {
            m = p;
        } else {
            continue;
        }
    }

    return m;
}
0
void4096

Hier ist mein Weg. Ich versuche, die Datenfeile zu gruppieren. 

const _ = require("underscore")

var test  = [ 1, 1, 2, 1 ];
var groupResult = _.groupBy(test, (e)=> e);

Das groupResult sollte sein 

{
  1: [1, 1, 1]
  2: [2] 
}

Suchen Sie dann die Eigenschaft, die das längste Array hat

function findMax(groupResult){
   var maxArr = []
   var max;
   for(var item in groupResult){
     if(!max) { 
        max = { value:item, count: groupResult[item].length } ; 
        maxArr.Push(max); 
        continue;
     }
     if(max.count < groupResult[item].length){ 
        maxArr = [];
        max = { value:item, count: groupResult[item].length }
        maxArr.Push(max)
     } else if(max === groupResult[item].length)
        maxArr.Push({ value:item, count: groupResult[item].length })
   }
   return maxArr;
}

Der vollständige Code sieht so aus

const _ = require("underscore")

var test  = [ 1, 1, 2, 1 ];
var groupResult= _.groupBy(test, (e)=> e);
console.log(findMax(groupResult)[0].value);

function findMax(groupResult){
   var maxArr = []
   var max;
   for(var item in groupResult){
     if(!max) { 
        max = { value:item, count: groupResult[item].length } ; 
        maxArr.Push(max); 
        continue;
     }
     if(max.count < groupResult[item].length){ 
        maxArr = [];
        max = { value:item, count: groupResult[item].length }
        maxArr.Push(max)
     } else if(max === groupResult[item].length)
        maxArr.Push({ value:item, count: groupResult[item].length })
   }
   return maxArr;
}
0
Andy Lai
var array = [1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17],
    c = {}, // counters
    s = []; // sortable array

for (var i=0; i<array.length; i++) {
    c[array[i]] = c[array[i]] || 0; // initialize
    c[array[i]]++;
} // count occurrences

for (var key in c) {
    s.Push([key, c[key]])
} // build sortable array from counters

s.sort(function(a, b) {return b[1]-a[1];});

var firstMode = s[0][0];
console.log(firstMode);
0
David Rosson

Diese Funktion ist eine generische Funktion für jede Art von Informationen. Es zählt das Vorkommen der Elemente und gibt dann ein Array mit maximal auftretenden Elementen zurück. 

function mode () {
  var arr = [].slice.call(arguments);
  if ((args.length == 1) && (typeof args[0] === "object")) {
    args = args[0].mode();
  }

  var obj = {};
  for(var i = 0; i < arr.length; i++) {
    if(obj[arr[i]] === undefined) obj[arr[i]] = 1;
    else obj[arr[i]]++;
  }

  var max = 0;
  for (w in obj) {
    if (obj[w] > max) max = obj[w];
  }

  ret_val = [];
  for (w in obj) {
    if (obj[w] == max) ret_val.Push(w);
  }

  return ret_val;
}

Mit ES6 können Sie die Methode folgendermaßen verketten:

    function findMostFrequent(arr) {
      return arr
        .reduce((acc, cur, ind, arr) => {
          if (arr.indexOf(cur) === ind) {
            return [...acc, [cur, 1]];
          } else {
            acc[acc.indexOf(acc.find(e => e[0] === cur))] = [
              cur,
              acc[acc.indexOf(acc.find(e => e[0] === cur))][1] + 1
            ];
            return acc;
          }
        }, [])
        .sort((a, b) => b[1] - a[1])
        .filter((cur, ind, arr) => cur[1] === arr[0][1])
        .map(cur => cur[0]);
    }
    
    console.log(findMostFrequent(['pear', 'Apple', 'orange', 'Apple']));
    console.log(findMostFrequent(['pear', 'Apple', 'orange', 'Apple', 'pear']));

Wenn zwei Elemente dasselbe Vorkommen haben, werden beide zurückgegeben. Und es funktioniert mit jeder Art von Element.

0
Vu Huu Cuong
// O(n)
var arr = [1, 2, 3, 2, 3, 3, 5, 6];
var duplicates = {};
max = '';
maxi = 0;
arr.forEach((el) => {
    duplicates[el] = duplicates[el] + 1 || 1;
  if (maxi < duplicates[el]) {
    max = el;
    maxi = duplicates[el];
  }
});
console.log(max);
0
indrajeet

Sie könnten es in O(n) Komplexität lösen

var arr = [1,3,54,56,6,6,1,6];
var obj = {};

/* first convert the array in to object with unique elements and number of times each element is repeated */
for(var i = 0; i < arr.length; i++)
{
   var x = arr[i];
   if(!obj[x])
     obj[x] = 1;
   else 
     obj[x]++;
}

console.log(obj);//just for reference

/* now traverse the object to get the element */
var index = 0;
var max = 0;

for(var obIndex in obj)
{
  if(obj[obIndex] > max)
  {
    max = obj[obIndex];
    index = obIndex;
  }
}
console.log(index+" got maximum time repeated, with "+ max +" times" );

Kopieren Sie einfach die Chrom-Konsole, um den obigen Code auszuführen.

0
Sandeep Gantait

Ich denke, Sie haben zwei Ansätze. Beides hat Vorteile.

Sortieren Sie dann Count oder Loop Through und verwenden Sie eine Hashtabelle, um die Zählung für Sie durchzuführen. 

Die Hashtabelle ist Nizza, denn wenn Sie mit der Verarbeitung fertig sind, haben Sie auch alle unterschiedlichen Elemente. Wenn Sie jedoch Millionen von Elementen hatten, könnte die Hashtabelle bei geringer Duplizierungsrate viel Speicherplatz beanspruchen. Der Sortier- und dann Zählansatz hätte einen viel kontrollierbareren Speicherbedarf.

0
Steve Sheldon
function mode(){
  var input = $("input").val().split(",");
  var mode = [];
  var m = [];
  var p = [];
    for(var x = 0;x< input.length;x++){
      if(m.indexOf(input[x])==-1){
        m[m.length]=input[x];
    }}
  for(var x = 0; x< m.length;x++){
    p[x]=0;
    for(var y = 0; y<input.length;y++){
      if(input[y]==m[x]){
      p[x]++; 
 }}}
 for(var x = 0;x< p.length;x++){
   if(p[x] ==(Math.max.apply(null, p))){
     mode.Push(m[x]);
 }} 
$("#output").text(mode);}
0
Harris Mowbray