รับองค์ประกอบที่เกิดขึ้นสูงสุดในอาร์เรย์


87

ฉันกำลังมองหาวิธีที่สวยงามในการพิจารณาว่าองค์ประกอบใดมีจำนวนเหตุการณ์สูงสุด ( โหมด ) ในอาร์เรย์ JavaScript

ตัวอย่างเช่นใน

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

'apple'องค์ประกอบหนึ่งที่พบบ่อยที่สุด


คุณสามารถปรับแนวคิดบางอย่างจากคำถาม Stackoverflow นี้ stackoverflow.com/questions/840781/…
Nosredna

ฉันไม่ได้อ่านวิธีแก้ปัญหาอย่างใกล้ชิดเกินไป แต่มีการรวมความแตกต่างกันเล็กน้อยต่อไปนี้ (การเพิ่มประสิทธิภาพ?) ตามข้อกำหนดเพียงเพื่อพิจารณาว่าองค์ประกอบใดมีเหตุการณ์ที่เกิดขึ้นมากที่สุดแทนที่จะเป็นจำนวนครั้งที่เกิดขึ้นมากที่สุด .... และความแตกต่างนั้นก็คือเมื่ออาร์เรย์ถูกวนซ้ำการนับสามารถหยุดได้เมื่อความแตกต่างระหว่างการเกิดขึ้นสูงสุดและสูงสุดอันดับสองน้อยกว่าจำนวนองค์ประกอบที่เหลือให้วนซ้ำการวนซ้ำสามารถหยุดได้ค่าสูงสุดในปัจจุบันจะสูงที่สุด
Dexygen

1
นอกจากนี้โซลูชันเหล่านี้ดูเหมือนจะไม่เกี่ยวข้องกับความสัมพันธ์
Dexygen

1
ในกรณีที่คุณกำลังมองหาโซลูชันอื่น (ซึ่งเล็กกว่าเล็กน้อย) stackoverflow.com/questions/40410470/…
daanvanham

คำตอบ:


95

นี่เป็นเพียงโหมด นี่เป็นวิธีแก้ปัญหาที่รวดเร็วและไม่เหมาะสม ควรเป็น 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;
}

1
ดี ... แต่ใช้ได้กับสตริงเท่านั้น - ไม่จำเป็นต้องเป็นข้อ จำกัด แต่เป็นสิ่งที่ต้องพิจารณา
เจมส์

ขอบคุณมากฉันไม่ได้คาดหวังวิธีแก้ปัญหาที่สมบูรณ์ ใช้ได้กับทั้งสตริงและตัวเลขด้วยการส่งผ่านเพียงครั้งเดียวซึ่งค่อนข้างดี
จับ

1
ฉันได้เพิ่มเวอร์ชันของอัลกอริทึมนี้เพื่อจัดการความสัมพันธ์
samandmoore

3
ฉันต้องแทนที่ `f (modeMap [el] == null) ด้วย if (! modeMap [el]) เนื่องจากมันทำให้ฉันมีตัวเลขที่ไม่ดีเมื่อผ่าน [2, 3, 3] เนื่องจาก modeMap [el] ไม่ได้กำหนดไว้ไม่ใช่ null
Naz

1
ฉันคิดว่ามันสมเหตุสมผลที่จะมีไทเบรกเกอร์ซึ่งในกรณีนี้คือองค์ประกอบที่มาก่อนในอาร์เรย์ แต่คุณสามารถปรับเปลี่ยนอัลกอริทึมนี้ได้อย่างง่ายดายเพื่อให้แต่ละส่วนเชื่อมโยงกันมากที่สุด
Wylliam Judd

63

มีการพัฒนาจาวาสคริปต์ตั้งแต่ปี 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โทรล่วงหน้า


แก้ไข:การปรับปรุงตัวอย่างที่มีบางส่วนES6 ลูกศรไขมันเพราะ2015ที่เกิดขึ้นและผมคิดว่าพวกเขาดูสวย ... ถ้าคุณมีความกังวลกับความเข้ากันได้คุณสามารถหานี้ในประวัติการแก้ไข


นี่มันเยี่ยมมาก! ตอนนี้คุณจะตอบกลับหลายคำตอบได้อย่างไรหากมีมากกว่าหนึ่งรายการในอาร์เรย์ที่เกิดขึ้นเหมือนกับรายการอื่น
Crystal

มันไร้เดียงสาที่ถือว่าโหมดไม่ซ้ำกันหากคุณต้องการให้ส่งคืนมากกว่าหนึ่งรายการคุณต้องติดตามจำนวนรวมสำหรับแต่ละรายการที่ดูไม่สวย ... คุณสามารถลองสิ่งนี้ได้เป็นเรื่องง่ายที่จะใช้ได้เฉพาะกับค่าดั้งเดิมเท่านั้น (แต่คุณสามารถปรับเปลี่ยนเพิ่มเติมได้หากจำเป็น)
ทูต

15
หากนี่ไม่ใช่โค้ดที่สวยงามฉันไม่รู้ว่าคืออะไร เป็นเหมือนโฆษณาสำหรับการเขียนโปรแกรมเชิงฟังก์ชัน
Sam H.

1
@GoranJakovljevic คุณเจาะจงมากขึ้นได้ไหม ฉันคิดว่ามันเป็นฟังก์ชันลูกศร ES6 - คุณลองใช้ตัวอย่างที่เข้ากันได้ย้อนหลังในประวัติการแก้ไขหรือไม่?
ทูต

คุณถูกต้องลูกศรของฟังก์ชัน ใช่การย้อนกลับทำงานได้ดี
Goran Jakovljevic

38

ตาม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;
}

ในตัวอย่างข้างต้นคุณจะสามารถจัดการผลลัพธ์ของฟังก์ชันเป็นอาร์เรย์ของโหมดได้


1
ในตัวอย่างที่สอง (อาร์เรย์หนึ่ง); คุณไม่จำเป็นต้องไปยังชุดmodesเพื่อ[array[0]]เป็นค่าเริ่มต้น modesซึ่งจะทำให้แน่ใจว่าคุณมีซ้ำกันใน นี่ควรทำเคล็ดลับvar modes = []
vdclouis

1
นี่มันเยี่ยมมาก! อย่างไรก็ตามเมื่อฉันทดสอบสิ่งนี้กับอาร์เรย์ที่มีค่าต่างกันสองค่าจะส่งคืนรายการแรกในอาร์เรย์สองครั้ง ไม่แน่ใจว่าทำไมถึงเกิดขึ้น ...
Crystal

@xgrioux ทำการเปลี่ยนแปลงตามที่ vdclouis แนะนำเพื่อต่อต้านข้อบกพร่องนี้ เช่นเปลี่ยน [array [0]] เป็น []
Dave Haigh

แนะนำให้เปลี่ยนกรณีของ==การ===ที่จะบังคับใช้อย่างเข้มงวดเท่าเทียมกัน
บางเลนโจเซฟ

16

จากคำตอบ ES6 + ของEmissaryคุณสามารถใช้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 เป็นตัวเลือกที่เป็นไปได้ที่คุณกำลังกรองบางทีนั่นอาจเป็นอาร์กิวเมนต์ที่สองที่เป็นทางเลือก

ข้อเสียเช่นเดียวกับวิธีแก้ปัญหาอื่น ๆ คือมันไม่ได้จัดการกับ 'สถานะการวาด' แต่ก็ยังสามารถทำได้ด้วยฟังก์ชันลดที่เกี่ยวข้องเล็กน้อย


14
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] }
}

นี่ยังคงเป็น O (n) แต่ใช้สองใบโดยไม่จำเป็น
Matthew Flaschen

2
เนื่องจากมีการส่ง JavaScript จึงน่าสนใจเสมอที่จะเห็นโซลูชันขนาดเล็ก
Nosredna

ฮ่า ๆ 2 ลบสำหรับวิธีแก้ปัญหาที่เหมาะสม] ฉันแก้ไขสองรอบโดยไม่จำเป็นทำให้มันเร็ว แต่ก็ยังใช้งานได้และยังคงเป็นวิธีแก้ปัญหาที่สั้นที่สุด
นักคิด

การเข้าถึง b แต่ละครั้งต้องใช้ log (len (b)) เป็นอย่างน้อยดังนั้น O (n) อาจมองโลกในแง่ดีหน่อย
Nicolas78

nicolas78: ถ้าอาร์เรย์มีขนาดเล็กก็ไม่สำคัญ ดังนั้นจึงขึ้นอยู่กับโครงการของคุณ
นักคิด

7

เมื่อฉันใช้ฟังก์ชันนี้เป็นแบบทดสอบสำหรับผู้สัมภาษณ์ฉันจึงโพสต์วิธีแก้ปัญหาของฉัน:

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

6

ลองใช้วิธีการประกาศที่นี่ โซลูชันนี้สร้างวัตถุเพื่อรวบรวมเหตุการณ์ที่เกิดขึ้นของแต่ละคำ จากนั้นกรองออบเจ็กต์ลงไปที่อาร์เรย์โดยเปรียบเทียบจำนวนที่เกิดขึ้นทั้งหมดของแต่ละคำกับค่าสูงสุดที่พบในออบเจ็กต์

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

กรุณาอธิบายคำตอบของคุณ
Haris

ฉันจะหลีกเลี่ยงการคำนวณค่าสูงสุดในลูปตัวกรองและลบคำสั่งแผนที่แบบคีย์ต่อค่า แม้ว่าคำตอบนี้จะไม่ได้ผลดีที่สุด แต่ก็ไม่เลวร้ายเท่ากับการกรองในตัวลดและเป็นสิ่งที่ดีและอ่านได้ const maxValue = Math.max (... Object.values ​​(ผลรวม)); ผลลัพธ์ const = keys.filter (x => ผลรวม [x] === maxValue);
milesaron

3

ถึงเวลาสำหรับวิธีแก้ปัญหาอื่น:

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

หากความกะทัดรัดมีความสำคัญ (ไม่เป็นเช่นนั้น):

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

หากต้องการหลีกเลี่ยงสมาชิกที่ไม่มีอยู่จริง (เช่นอาร์เรย์แบบกระจัดกระจาย) จะมีhasOwnPropertyเพิ่มเติมจำเป็นต้องมีการทดสอบ :

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

คำตอบอื่น ๆ ที่นี่จะกลับมาไม่ได้กำหนด


@ โยนาห์ - ความสั้นเพื่อประโยชน์ของตัวมันเองนั้นไม่มีจุดหมายและมักจะทำให้อ่านและดูแลรักษาโค้ดได้ยากขึ้น แน่นอนว่าโค้ด verbose ที่มากขึ้นนั้นไม่จำเป็นต้องดีขึ้นเพียงเพื่อให้ยาวขึ้น แต่เกณฑ์เหล่านั้นของตัวเองถูกขัดขวางโดยมาตรการที่สำคัญกว่ามากเช่นความชัดเจนและการบำรุงรักษา
RobG

เห็นได้ชัดว่าความหนาแน่นที่คลุมเครือไม่เคยเป็นเป้าหมาย แต่โดยทั่วไปแล้วรหัสเดียวกันสองเวอร์ชันที่มีความหนาแน่นเท่ากันโดยประมาณอันที่สั้นกว่ามักจะชัดเจนและดีกว่า ฉันไม่ได้บอกว่ามันเป็นกฎแต่ความสัมพันธ์นั้นแข็งแกร่ง ในความเป็นจริงผมว่าไม่มีอื่นใดอีกเดียวตัวบ่งชี้ความสัมพันธ์อย่างมากกับการอ่าน นี่คือเหตุผลที่โปรแกรมเมอร์ทุกคนชอบลบโค้ด ด้วยเหตุนี้การเขียนซ้ำส่วนใหญ่ใน Code Review จึงสั้นกว่าต้นฉบับ
โยนาห์

3

โซลูชัน JS อื่นจาก: https://www.w3resource.com/javascript-exercises/javascript-array-exercise-8.php

สามารถลองสิ่งนี้ได้เช่นกัน:

let arr =['pear', 'apple', 'orange', 'apple'];

function findMostFrequent(arr) {
  let mf = 1;
  let m = 0;
  let item;

  for (let i = 0; i < arr.length; i++) {
    for (let j = i; j < arr.length; j++) {
      if (arr[i] == arr[j]) {
        m++;
        if (m > mf) {
          mf = m;
          item = arr[i];
        }
      }
    }
    m = 0;
  }

  return item;
}

findMostFrequent(arr); // apple

3

นี่คืออีกวิธีหนึ่งของ ES6 ในการดำเนินการด้วยความซับซ้อน O (n)

const result = Object.entries(
    ['pear', 'apple', 'orange', 'apple'].reduce((previous, current) => {
        if (previous[current] === undefined) previous[current] = 1;
        else previous[current]++;
        return previous;
    }, {})).reduce((previous, current) => (current[1] >= previous[1] ? current : previous))[0];
console.log("Max value : " + result);

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

ปัญหาในการแก้ปัญหานี้คือคำว่า "สูงสุด" และ "โหมด" จะไม่นับเป็นส่วนหนึ่งของตรรกะในแผนที่ ...
Pablo

2

นี่คือวิธีแก้ปัญหาของฉัน แต่มีตัวเลขและใช้คุณสมบัติ 'Set' ใหม่ มันไม่ค่อยมีประสิทธิภาพ แต่ฉันสนุกมากกับการเขียนสิ่งนี้และมันรองรับค่าสูงสุดหลายค่า

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]

อย่างไรก็ตามอย่าใช้สิ่งนี้ในการผลิตนี่เป็นเพียงภาพประกอบของวิธีการแก้ปัญหาด้วยฟังก์ชัน ES6 และ Array เท่านั้น


2

นี่คือทางออกของฉัน: -

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']))


2

เพื่อประโยชน์ในการอ่านรหัสที่บำรุงรักษาได้ง่ายฉันแบ่งปันสิ่งนี้:

function getMaxOcurrences(arr = []) {
  let item = arr[0];
  let ocurrencesMap = {};

  for (let i in arr) {
    const current = arr[i];

    if (ocurrencesMap[current]) ocurrencesMap[current]++;
    else ocurrencesMap[current] = 1;

    if (ocurrencesMap[item] < ocurrencesMap[current]) item = current;
  }

  return { 
    item: item, 
    ocurrences: ocurrencesMap[item]
  };
}

หวังว่าจะช่วยใครบางคน;)!


2

โซลูชันนี้สามารถส่งคืนหลายองค์ประกอบของอาร์เรย์ในกรณีที่เสมอกัน ตัวอย่างเช่นอาร์เรย์

arr = [ 3, 4, 3, 6, 4, ];

มีค่าโหมดสองค่า: 3และ6.

นี่คือวิธีแก้ปัญหา

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

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

หมายเหตุ: ct คือความยาวของอาร์เรย์

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
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'))

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

1

ลองใช้เช่นกันสิ่งนี้ไม่ใช้ในเวอร์ชันเบราว์เซอร์ของบัญชี

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']));

โปรดทราบว่าฟังก์ชันนี้จะคืนค่าการเกิดล่าสุดในอาร์เรย์เมื่อ 2 รายการขึ้นไปปรากฏในจำนวนครั้งเท่ากัน!


1
// 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);

1

นี่คือเวอร์ชันที่ทันสมัยที่ใช้แผนที่ในตัว (ดังนั้นจึงทำงานได้มากกว่าสิ่งต่างๆที่สามารถแปลงเป็นสตริงที่ไม่ซ้ำกันได้):

'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

ฉันเดาว่าคุณมีสองวิธี ซึ่งทั้งสองอย่างนี้มีข้อดี

เรียงลำดับจากนั้นนับหรือวนซ้ำและใช้ตารางแฮชเพื่อทำการนับให้คุณ

แฮชแท็กเป็นสิ่งที่ดีเพราะเมื่อคุณประมวลผลเสร็จแล้วคุณจะมีองค์ประกอบที่แตกต่างกันทั้งหมด หากคุณมีรายการหลายล้านรายการตารางแฮชอาจใช้หน่วยความจำจำนวนมากหากอัตราการทำสำเนาต่ำ วิธีการเรียงลำดับแล้วนับจะมีรอยเท้าหน่วยความจำที่ควบคุมได้มากกว่า


0
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

คุณสามารถลองสิ่งนี้:

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

คุณสามารถแก้ปัญหาได้ในความซับซ้อน O (n)

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" );

เพียงคัดลอกและวางในคอนโซล Chrome เพื่อเรียกใช้โค้ดด้านบน


0

ฟังก์ชันนี้เป็นฟังก์ชันทั่วไปสำหรับข้อมูลทุกประเภท นับการเกิดขึ้นขององค์ประกอบจากนั้นส่งคืนอาร์เรย์ที่มีองค์ประกอบที่เกิดขึ้นสูงสุด

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

0
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

นี่คือทางของฉัน ฉันพยายามจัดกลุ่มข้อมูล

const _ = require("underscore")

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

groupResult ควรเป็น

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

จากนั้นหาคุณสมบัติที่มีอาร์เรย์ที่ยาวที่สุด

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

รหัสที่สมบูรณ์มีลักษณะดังนี้

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

ด้วย ES6 คุณสามารถเชื่อมโยงวิธีการดังนี้:

    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']));

หากสององค์ประกอบมีการเกิดขึ้นเหมือนกันมันจะส่งคืนทั้งสองอย่าง และใช้ได้กับองค์ประกอบทุกประเภท


คุณไม่ควรใช้ตัวแปรarrภายในขอบเขตที่ตัวแปรนั้นถูกกำหนดเป็นพารามิเตอร์แล้ว ซึ่งอาจทำให้เกิดข้อบกพร่องขึ้นอยู่กับเบราว์เซอร์ที่ใช้
mesqueeb

ที่arrอ้างถึงโดยarr.indexOf(cur)? พารามิเตอร์ด้านบนหรือพารามิเตอร์ภายในการลด ??
mesqueeb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.