找到数组中最常见的项(不仅仅是字符串)

时间:2015-07-05 06:22:42

标签: javascript arrays algorithm

有人可以引导我完成这个exercise吗? 编写一个JavaScript程序来查找数组中最常见的项目。



var arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var mf = 1;
var m = 0;
var item;

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

  m = 0;
}

alert(item + " ( " + mf + " times ) ");
&#13;
&#13;
&#13;

我已经在stackoverflow上查看了一些类似的问题,但却无法找到我想要的答案。

我的问题是:

  1. 我不明白为什么需要有两个for循环。

  2. 为什么需要mfm。似乎有点令人困惑。

  3. 还有其他方法可以解决这个问题吗?

8 个答案:

答案 0 :(得分:2)

用户想要解释代码:

在这里,他们选择数组的第一个元素,然后将其与每个元素进行比较。

然后,每当相同的元素再次出现时,它们会递增计数器m,即该元素的频率。

还保留变量mf以跟踪最大频率。将元素频率与最大频率进行比较,并根据当前元素的频率更新itemmf

var arr1=[3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]; //array
var mf = 1; //default maximum frequency
var m = 0;  //counter
var item;  //to store item with maximum frequency
for (var i=0; i<arr1.length; i++)    //select element (current element)
{
        for (var j=i; j<arr1.length; j++)   //loop through next elements in array to compare calculate frequency of current element
        {
                if (arr1[i] == arr1[j])    //see if element occurs again in the array
                 m++;   //increment counter if it does
                if (mf<m)   //compare current items frequency with maximum frequency
                {
                  mf=m;      //if m>mf store m in mf for upcoming elements
                  item = arr1[i];   // store the current element.
                }
        }
        m=0;   // make counter 0 for next element.
}

答案 1 :(得分:2)

  

我不明白为什么需要有两个for循环。

除作者选择外,不需要两个循环。

  

为什么需要mfm。似乎有点令人困惑。

它们是作者选择的解决方案所必需的。

m是要测试的当前值的计数。

mf是当前测试m的最大频率,如果正在测试的当前元素比以前最频繁的频率更频繁,则会做出决定。

  

还有其他方法可以解决这个问题吗?

当然,很多。这是另一个更进一步的方法。

function getMostFrequentElement(inputArg) {
    var type = typeof inputArg,
        length,
        mostFrequent,
        counts,
        index,
        value;
    
    if (inputArg === null || type === 'undefined') {
        throw TypeError('inputArg was "null" or "undefined"');
    }

    mostFrequent = [];
    if (type === 'function' || !Object.prototype.hasOwnProperty.call(inputArg, 'length')) {
        mostFrequent[0] = inputArg;
        mostFrequent[1] = 1;
    } else {
        counts = {};
        length = inputArg.length;
        for (index = 0; index < length; index += 1) {
            value = inputArg[index];
            type = typeof value;
            counts[type] = counts[type] || {};
            counts[type][value] = (counts[type][value] || 0) + 1;
            if (!mostFrequent.length || counts[type][value] >= mostFrequent[1]) {
                mostFrequent[0] = value;
                mostFrequent[1] = counts[type][value];
            }
        }
    }

    return mostFrequent;
}

function logMostFrequentElement(inputArg) {
    var mostFrequentElement,
    element,
    text;

    try {
        mostFrequentElement = getMostFrequentElement(inputArg)
        if (mostFrequentElement.length) {
            element = mostFrequentElement[0];
            if (typeof element === 'string') {
                element = '"' + element + '"';
            }

            text = element + ' ( ' + mostFrequentElement[1] + ' times )';
        } else {
            text = 'No elements';
        }
    } catch (e) {
        text = e.message;
    }

    document.getElementById('out').appendChild(document.createTextNode(text + '\n'));
}

logMostFrequentElement();
logMostFrequentElement(1);
logMostFrequentElement(true);
logMostFrequentElement(function (x) { return x; });
logMostFrequentElement(/ab/g);
logMostFrequentElement([]);
logMostFrequentElement([1, 2]);
logMostFrequentElement([1, NaN, 2, NaN, 'NaN']);
logMostFrequentElement([1, Infinity, 2, Infinity, 'Infinity', -Infinity]);
logMostFrequentElement(['1', '2', 1, '2', 2]);
logMostFrequentElement([3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]);
logMostFrequentElement([34, 'ab', 'ab', 'ab', 21, 34, 'ab', 34, 'ab', 21, 45, 99, 34]);
logMostFrequentElement('Also works with strings.');
<pre id="out"></pre>

答案 2 :(得分:1)

我真的认为在这个解决方案中不需要2个循环。 您可以查看这个使用名为map的简单数据结构的原型代码:

var arr=[3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var map = {};
var mostFrequentElement = arr[0];
function findMostFrequent(){
    for(var i = 0; i<arr.length; i++){
        if(!map[arr[i]]){
            map[arr[i]]=1;
        }else{
            ++map[arr[i]];
            if(map[arr[i]]>map[mostFrequentElement]){
                mostFrequentElement = arr[i];
            }
        }
    }
    alert(mostFrequentElement);
}

答案 3 :(得分:1)

这是使用下划线的第(3)点的答案:

function length(a) { return a.length; }

_.max(_.groupBy(arr1), length)[0]

这是如何运作的:

> arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];

> groups = _.groupBy(arr1)
< { 2: [2,2], 3: [3,3,3,3], 4: [4], 9: [9], a: ['a', 'a', ...] }

> max_group = _.max(groups, length)
< ['a', 'a', ...]

> max_group [0]
< 'a'

答案 4 :(得分:0)

var nums = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3]; //array
var freqs = {};
var max_index;
var max_value = -1/0; // Negative infinity.

$.each(nums, function(i, v) {
  if (freqs[v] != undefined) {
  freqs[v]++;
} else {
    freqs[v] = 1;
}
});


$.each(freqs, function(num, freq) {
  if (freq > max_value) {
      max_value = freq;
      max_index = num;
    }
});

if(max_index != undefined) {
    alert("Most common element is " + max_index + " with " + max_value + "  repetition(s).");
}

答案 5 :(得分:0)

使用 Array.prototype.reduce() 和一个临时变量,您可以这样做(4行):

&#13;
&#13;
var arr2 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
var newArr = arr2.slice().sort(), most = [undefined, 0], counter = 0;

newArr.reduce(function(old, chr){
   old == chr ? ++counter > most[1] && (most = [chr, counter]) : (counter = 1)
   return chr
});

alert(most[0] + " ( "+most[1]+" times )");
&#13;
&#13;
&#13;

解释 请原谅我的英文。

使用 Array.prototype.reduce() 可以简化您的工作。以下函数首先将其字符排序为22333349aaaaa,然后按顺序计算字符数。我创建了一个临时变量most来存储最重复的字符数据。

  

注意这仅适用于个位数的项目。

答案 6 :(得分:0)

请试试这个。

var mostFrequnet = null,mostFrequnetItem ;
var arr1 = [3, 'a', 'a', 'a', 2, 3, 'a', 3, 'a', 2, 4, 9, 3];
arr1.sort();


for (var i=0;i<arr1.length;i++){ 

     var single = arr1[i]; 
     var total = (arr1.lastIndexOf(single)-arr1.indexOf(single))+1; 

     if(total > mostFrequnet) {

         mostFrequnetItem = arr1[i];
         mostFrequnet = total;
         i= arr1.lastIndexOf(single)+1;

    }
}

console.log(mostFrequnet);

console.log(mostFrequnetItem);

答案 7 :(得分:-1)

mf 是频率最高的数字的全局计数,m 是 inisde 循环中的局部计数