查找数组元素出现的次数

25

我刚接触JavaScript,已经学习和练习了大约3个月了,希望在这个主题上能得到一些帮助。我正在制作一个扑克游戏,我想做的是确定我有一对、两对、三条、四条或一个葫芦。

例如,在[1, 2, 3, 4, 4, 4, 3]中,1出现1次,4出现3次,等等。

我怎么可能让我的计算机告诉我数组元素出现的次数?

解决了,这是最终成果。

    <script type="text/javascript">
    var deck = [];
    var cards = [];
    var convertedcards = [];
    var kinds = [];
    var phase = 1;
    var displaycard = [];
    var options = 0;
    var endgame = false;

    // Fill Deck //
    for(i = 0; i < 52; i++){
        deck[deck.length] = i;          
    }

    // Distribute Cards //
    for(i = 0; i < 7; i++){
        cards[cards.length] = Number(Math.floor(Math.random() * 52));
        if(deck.indexOf(cards[cards.length - 1]) === -1){
            cards.splice(cards.length - 1, cards.length);
            i = i - 1;
        }else{
            deck[cards[cards.length - 1]] = "|";
        }
    }

    // Convert Cards //
    for(i = 0; i < 7; i++){
        convertedcards[i] = (cards[i] % 13) + 1;
    }


    // Cards Kind //
    for(i = 0; i < 7; i++){
        if(cards[i] < 13){
            kinds[kinds.length] = "H";
        }else if(cards[i] < 27 && cards[i] > 12){
            kinds[kinds.length] = "C";
        }else if(cards[i] < 40 && cards[i] > 26){
            kinds[kinds.length] = "D";
        }else{
            kinds[kinds.length] = "S";
        }
    }

    // Card Display //
    for(i = 0; i < 7; i++){
        displaycard[i] = convertedcards[i] + kinds[i];
    }

    // Hand Strenght //
    var handstrenght = function(){
        var usedcards = [];
        var count = 0;
        var pairs = [];
        for(i = 0, a = 1; i < 7; a++){
            if(convertedcards[i] === convertedcards[a] && a < 7 && usedcards[i] != "|"){
                pairs[pairs.length] = convertedcards[i];
                usedcards[a] = "|";
            }else if(a > 6){
                i = i + 1;
                a = i;
            }
        }

        // Flush >.< //
        var flush = false;
        for(i = 0, a = 1; i < 7; i++, a++){
            if(kinds[i] === kinds[a] && kinds[i] != undefined){
                count++;
                if(a >= 6 && count >= 5){
                    flush = true;
                    count = 0;
                }else if(a >= 6 && count < 5){
                    count = 0;
                }
            }
        }
        // Straight >.< //
        var straight = false;
        convertedcards = convertedcards.sort(function(a,b){return a-b});
        if(convertedcards[2] > 10 && convertedcards[3] > 10 && convertedcards[4] > 10){
            convertedcards[0] = 14;
            convertedcards = convertedcards.sort(function(a,b){return a-b});
        }
        alert(convertedcards);
        if(convertedcards[0] + 1 === convertedcards[1] && convertedcards[1] + 1 === convertedcards[2] && convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4]){
            straight = true;
        }else if(convertedcards[1] + 1 === convertedcards[2] && convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4] && convertedcards[4] + 1 === convertedcards[5]){
            straight = true;
        }else if(convertedcards[2] + 1 === convertedcards[3] && convertedcards[3] + 1 === convertedcards[4] && convertedcards[4] + 1 === convertedcards[5] && convertedcards[5] + 1 === convertedcards[6]){
            straight = true;
        }
        // Royal Flush, Straight Flush, Flush, Straight >.< //
        var royalflush = false;
        if(straight === true && flush === true && convertedcards[6] === 14){
            royalflush = true;
            alert("You have a Royal Flush");
        }
        else if(straight === true && flush === true && royalflush === false){
            alert("You have a straight flush");
        }else if(straight === true && flush === false){
            alert("You have a straight");
        }else if(straight === false && flush === true){
            alert("You have a flush");
        }
        // Full House >.< //
        if(pairs[0] === pairs[1] && pairs[1] != pairs[2] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }else if(pairs[0] != pairs[1] && pairs[1] === pairs[2] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }else if(pairs[0] != pairs[1] && pairs[1] != pairs[2] && pairs[2] === pairs[3] && pairs.length >= 3){
            fullhouse = true;
            alert("You have a fullhouse");
        }
        // Four of a kind >.< //
        else if(pairs[0] === pairs[1] && pairs[1] === pairs[2] && pairs.length > 0){
            alert("You have four of a kind");
        }
        // Three of a kind >.< //
        else if(pairs[0] === pairs[1] && flush === false && straight === false && pairs.length === 2){
            alert("You have three of a kind");
        }
        // Double Pair >.< //
        else if(pairs[0] != pairs[1] && flush === false && straight === false && pairs.length > 1){
            alert("You have a double pair");
        }
        // Pair >.< //
        else if(pairs.length === 1 && flush === false && straight === false && pairs.length === 1 ){
            alert("You have a pair");
        }
        alert(pairs);
    };
    while(endgame === false){
        if(phase === 1){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 2){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 3){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + " " + displaycard[5] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }else if(phase === 4){
            options = Number(prompt("Your hand: " + displaycard[0] + " " + displaycard[1] + "\n\n" + displaycard[2] + " " + displaycard[3] + " " + displaycard[4] + " " + displaycard[5] + " " + displaycard[6] + "\n\n" + "1. Check" + "\n" + "2. Fold"));
        }
        switch(options){
            case 1:
                    if(phase === 5){
                        handstrenght();
                        endgame = true;
                    }else{
                        phase++;
                    }
                    break;
            case 2:
                    endgame = true;
                    break;
            default:
                    endgame = true;
                    break;
        }
    }


</script>

7
你尝试过什么吗?我不想轻易地告诉你这个秘密或者阻止你获得学习经验 ;) - Ruan Mendes
你卡在哪里了?你知道如何使用“for”循环吗? - I Hate Lazy
1
@JuanMendes 如果可以的话,我会给你的评论点赞20次的 :-). - chuckj
7个回答

38
  • 保持一个变量用于存储总计数
  • 遍历数组并检查当前值是否与您要查找的值相同,如果是,则将总计数增加一
  • 循环后,总计数包含您要查找的数字在数组中出现的次数

展示您的代码,我们可以帮助您找出问题所在

这里有一个简单的实现(因为您没有提供不起作用的代码)

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

function countInArray(array, what) {
    var count = 0;
    for (var i = 0; i < array.length; i++) {
        if (array[i] === what) {
            count++;
        }
    }
    return count;
}

countInArray(list, 2); // returns 2
countInArray(list, 1); // returns 3

countInArray也可以这样实现

function countInArray(array, what) {
    return array.filter(item => item == what).length;
}

更加优雅,但可能不如效率高,因为它需要创建一个新的数组。


@FredericDaniel 展示你的代码,SO上的问题应该始终展示代码、期望/实际结果以及任何错误信息。 - Ruan Mendes
我的代码已经不存在了,一个月前我一直试图解决这个问题,连续尝试了6个小时后,我变得非常生气并删除了整个项目。 - Frederic Daniel
如果你无法让它正常工作,请再试一次并在这里发布,不要轻易放弃。 - Ruan Mendes
没关系,我所要做的就是加一个else if语句来判断'a'是否大于6。现在一切都正常了。 - Frederic Daniel
2
@Dake,你为什么不自己写一个并且在有问题的时候再提出另一个问题呢? - Ruan Mendes
显示剩余2条评论

14

使用filterlength似乎很简单,但会浪费大量内存。

如果您想使用优秀的数组方法,请选择适当的reduce方法:

function countInArray(array, value) {
  return array.reduce((n, x) => n + (x === value), 0);
}
console.log(countInArray([1,2,3,4,4,4,3], 4)); // 3


2
浪费大量内存 - 你能详细说明为什么吗? - vsync
1
顺便说一句,这真是太聪明了! - vsync

4

Well..

var a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
  if (typeof acc[curr] == 'undefined') {
    acc[curr] = 1;
  } else {
    acc[curr] += 1;
  }

  return acc;
}, {});

// a == {2: 5, 4: 1, 5: 3, 9: 1}

从这里开始:计算JavaScript数组元素的出现次数

或者您也可以在那里找到其他解决方案。


不错的复杂答案,但我认为这可能有点超出了提问者的能力范围。至少它没有直接给出答案,因为提问者仍需要学习很多才能理解正在发生的事情。另一方面,他们可能会使用您的方法,而从未真正理解它,这将背离 Stack Overflow 的宗旨。 - Ruan Mendes

2
当针对足够新的浏览器时,您可以使用 filter() 来实现。 (MDN页面还提供了该函数的 polyfill)。
var items = [1, 2, 3, 4, 4, 4, 3];
var fours = items.filter(function(it) {return it === 4;});
var result = fours.length;

您甚至可以将过滤函数抽象为以下形式:

// Creates a new function that returns true if the parameter passed to it is 
// equal to `x`
function equal_func(x) {
    return function(it) {
        return it === x;
    }
}
//...
var result = items.filter(equal_func(4)).length;

它自IE9开始就得到了支持。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Browser_compatibility - Ruan Mendes
@JuanMendes - 谢谢,我让答案的措辞更加准确。 - millimoose
1
这浪费了太多的内存。 - Oriol
1
@Oriol 它使用 O(N) 的内存,最坏情况下,对于可能很小的 N 值,内存开销在实际环境中完全不重要。如果你不能抽出那么多的内存,你可能无法存储原始数组。如果你需要处理大量数据集,并且正在寻找 SO 答案来解决学校作业问题,那么你有更糟糕的问题。 - millimoose
1
一种基于reduce的版本会更有效率,但是在我猜测原帖作者的技能水平下,reduce并不太易读。而且一个循环版本已经被接受作为答案了,所以我不会编辑一个四年前的答案,除非它明显是错误的,使其与投票结果大相径庭。 - millimoose

1
这是一个使用数组对象原型的实现,如果没有提供搜索项,它还具有额外的功能级别,返回长度:
Array.prototype.count = function(lit = false) {
    if ( !lit ) { return this.length}
    else {
        var count = 0;
        for ( var i=0; i < this.length; i++ ) {
            if ( lit == this[i] ){
                count++
            }
        }
        return count;
    }
}

这个非常简单易用,具体如下:

var count = [1,2,3,4,4].count(4);  // Returns 2
var count = [1,2,3,4,4].count();   // Without first parameter returns 5

2
避免篡改本地对象的原型,当Array.prototype.count方法被标准化时可能会不兼容。 - Ruan Mendes
这个程序会返回3,因为[1,2,3].count(0)中有3个0。我建议去掉只返回长度的情况。 - Ruan Mendes

1
这是Juan答案的一个实现:
function count( list, x ) {

    for ( var l = list.length, c = 0; l--; ) {

        if ( list[ l ] === x ) {

            c++;
        }
    }

    return c;

}

更短:
function count( list, x ) {

    for ( var l = list.length, c = 0; l--; list[ l ] === x && c++ );

    return c;

}

为什么要试图让它变短?让它简单,不需要优化。另外,如果你把它做成一个方法,你必须传入数组,请不要依赖全局变量。 - Ruan Mendes
@JuanMendes 我没有传递一个数组,只是值。list是OP在他的问题中声明的数组... :) - David G
我的观点是你应该传递它。count 应该将要计数的数组作为参数传入,而不是使用全局变量。否则,将其设置为函数就没有意义,因为它只能与你设置的那个全局变量一起使用。请参见我的答案。 - Ruan Mendes

0
避免对原生对象的原型进行修改,当Array.prototype.count方法被标准化时可能会产生不兼容性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接