【问题标题】:Using Linq to find if a list contains an incremental sequence of at least 5 values [duplicate]使用Linq查找列表是否包含至少5个值的增量序列[重复]
【发布时间】:2017-03-01 22:42:15
【问题描述】:

我正在开发一款扑克游戏,它计算出你拿到的牌是什么牌。我目前停留在顺子的逻辑上(5 张牌以增量顺序排列,例如 3、4、5、6、7)。我使用的 Card 对象有一个表示其值的 int 属性(ace 默认为 14)。

这是我目前所拥有的:

private static bool CheckForStraight()
{
        List<Card> tmpCards = new List<Card>(_cards); //local copy of the cards
        if (tmpCards.Count < 5) //need atleast 5 cards to make a straight
            return false;

        tmpCards = tmpCards.DistinctBy(v => v.CardValue).ToList(); //remove duplicate values
        tmpCards = tmpCards.OrderBy(x => x.CardValue).ToList(); //order list

        int count = 0;

        if (tmpCards.Zip(tmpCards.Skip(1), (a, b) => (a.CardValue + 1) == b.CardValue).Any(x => x))
        {
            count++;
        }
        else
        {
            count = 0;
        }
        return false;
}

运行此代码时,linq 表达式将检查列表中的任何卡片值是否按顺序排列...因此,如果列表包含值为 2、3、5、8、11 的卡片,它将 +1算作 2 和 3 是连续的。所以 count 总是要么是 0 要么是 1,这对我来说没用。理想情况下,如果顺序有五张牌,我希望计数为 5。然后,如果计数等于 5,我就可以继续找出构成顺子的牌。

(如果一个 linq 表达式可以确定哪 5 张卡片是按顺序排列的,那就更好了,不确定在一个表达式头脑中是否可能)。

我的问题:如何修改我当前的 linq 表达式以获得我需要的结果?或者,如果我以错误的方式进行此操作,我能否指出正确的方向,提前致谢。

【问题讨论】:

  • 简单的for 循环遍历排序数组有什么问题,而不是使用 LINQ。 ?在您的情况下,看起来代码会更加清晰。
  • 对于 5 张扑克这有效: List input = new List() { 1, 3, 5, 6, 7 };布尔直 = (input.Distinct().Count() == 5) && (input.Max() - input.Min() == 4);
  • 找到更好的解决方案,参见上面的编辑

标签: c# linq


【解决方案1】:

你已经接近了 - 只需检查每张卡片,然后将卡片放在后面 4 个位置,看看差异是否为 4。

private static bool CheckForStraight()
{
    List<Card> tmpCards = new List<Card>(_cards); //local copy of the cards
    if (tmpCards.Count < 5) //need atleast 5 cards to make a straight
        return false;

    tmpCards = tmpCards.DistinctBy(v => v.CardValue).ToList(); //remove duplicate values
    tmpCards = tmpCards.OrderBy(x => x.CardValue).ToList(); //order list

    return tmpCards
        .Zip(tmpCards.Skip(4), (a, b) => (a.CardValue + 4) == b.CardValue)
        .Any(x => x);
}

【讨论】:

  • @Chris OP 已经删除了重复值,所以你最终会得到 2、4、6 并且没有直线。
  • 非常感谢!工作一种享受。你知道有没有一种快速简便的方法可以根据 linq 表达式获取 5 张卡片?
  • @rejy11 不,这样的查询看起来会大不相同。
  • 好吧,别担心,祝我好运
【解决方案2】:

你在一个很好的轨道上,现在只需添加一个循环:

private static bool CheckForStraight()
{
    List<Card> tmpCards = _cards.DistinctBy(v => v.CardValue).OrderBy(v => v.CardValue).ToList();
    if(tmpCards.Count < 5) return false;

    int count = 0;

    for(int i = 1; i < tmpCards.Count; i++)
    {
        if(tmpCards[i] != tmpCards[i - 1] + 1 && count < 4) return false;
        count++;
    }
    return count >= 5;
}

【讨论】:

  • 再一次,在这里使用 LINQ 没有太多理由。 2 ToList() 调用 => 2 List&lt;T&gt; 来自一个,只需遍历已经存在且 有序 的集合即可找到连续数字的集群。
  • @AdamHouldsworth 我看不出它在1, 3, 2, 4, 5 上如何返回false,你还有另一个测试用例吗?
  • @HimBromBeere 对不起,你是对的。我所指的支票实际上是在&amp;&amp; count &lt; 4 末尾的if 中进行的。道歉。
猜你喜欢
  • 2015-07-23
  • 2012-08-05
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2012-11-15
  • 2018-03-13
相关资源
最近更新 更多