在List<>中查找数组出现的次数

4

我正在为我的网站开发一个统计数据部分,但是我遇到了一些困难,无法想出如何获取“热门事物”(下面有解释):

我有以下表格:

ID | Spell1ID | Spell2ID
1 | 4 | 12
2 | 4 | 12
3 | 12 | 4
4 | 1 | 8
5 | 3 | 12
6 | 8 | 1

为了获取那些数据,我正在执行以下操作:
List<short[]> spellsList = new List<short[]>();

..

            using (MySqlDataReader dbReader = Conex.Command.ExecuteReader())
            {
                while (dbReader.Read())
                {
                    short[] tempArray = new short[2];

                    tempArray[0] = dbReader.GetInt16("spell1ID");
                    tempArray[1] = dbReader.GetInt16("spell2ID");

                    spellsList.Add(tempArray);
                }
            }

现在,我需要计算哪些值是最常见的(从最常见到不太常见),并且列表中每个数组的值的顺序不重要([4,12]和[12,4]是相同的,因为我实际上只需要SpellID以及它被使用的频率),所以对于这个例子来说,结果应该是:
1- 4, 12 (3 times)
2- 1,8 (2 times)
3- 3,12

使用LINQ和Lambda表达式来完成这个任务会非常好。

如果我的表达令人困惑,请见谅,英语不是我的母语。


1
你尝试了什么?Stack Overflow是为帮助你编写自己的代码而存在的,而不是让其他人替你编写代码。请提供一个良好的[mcve],清楚地展示你所尝试的内容。话虽如此,根据你目前的描述(对我来说并不是很清楚),似乎你应该对tempArray进行排序,然后使用GroupBy()和一个IEqualityComparer来处理数组的比较。每个结果组的计数将告诉你每个组合出现的次数。 - Peter Duniho
1
@PeterDuniho 我完全同意StackOverflow能够帮助我编写自己的代码,并且如果我的问题不清楚,我很抱歉。我没有尝试任何特定的东西,因为我被逻辑本身所困扰。现在,有了Mangist的答案,我意识到应该如何使用LINQ来解决我的问题。感谢您的评论和时间。 - Daniel
2个回答

3
    static void Main(string[] args)
    {
        var spellsList = new List<short[]>();

        spellsList.Add(new short[] {4, 12 });
        spellsList.Add(new short[] {4, 12 });
        spellsList.Add(new short[] {12, 4 });
        spellsList.Add(new short[] { 1, 8});
        spellsList.Add(new short[] {3, 12});
        spellsList.Add(new short[] {8, 1 });
        spellsList.Add(new short[] {8, 1 });
        spellsList.Add(new short[] {8, 1 });
        spellsList.Add(new short[] {8, 1 });


        var result = spellsList.Select(s => s[0] > s[1] ? String.Format("{0},{1}", s[0], s[1]) : String.Format("{0},{1}", s[1], s[0]))
                               .GroupBy(s => s)
                               .OrderByDescending(g => g.Count())
                               .ToList();

        result.ForEach(g => Console.WriteLine($"{g.Key}: {g.Count()} times"));

        Console.Read();
    }

感谢Mangist的回答,它起作用了。现在我知道我必须深入学习LINQ,以便将来能够解决类似这样的问题。非常感激你的帮助。 - Daniel

0
// fake data
var data = @"1 | 4 | 12
            2 | 4 | 12
            3 | 12 | 4
            4 | 1 | 8
            5 | 3 | 12
            6 | 8 | 1"
.Split('\n')
.Select(x => x.Split(new[] { " | " }, StringSplitOptions.None));

var spellsList = data.Select(x => new[]
{
    int.Parse(x[1]), int.Parse(x[2])
});

// query
var combos = spellsList
    .GroupBy(spells => string.Join(", ", spells.OrderBy(x => x)), (k, g) => new
    {
        SpellCombo = k,
        CastCount = g.Count(),
    })
    .OrderBy(x => x.CastCount)
    .ToList();

foreach(var combo in combos)
{
    Console.WriteLine($"Combo {combo.SpellCombo} is casted {combo.CastCount} times. ");
}

感谢 Xiaoy312 的回答,你给了我另一种解决类似问题的方法。非常感谢你! - Daniel

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