通过一系列公共ID对对象进行分组,并根据LINQ中不同键的总和选择分组

时间:2016-04-21 19:13:49

标签: linq

所以我有一点学术问题。我能够使用蛮力方法解决这个问题,但我相信它在LINQ中可以更加优雅地解决 - 但是,我找不到这样做的方法。解决方案可以是C#或VB,它是LINQ本身给我带来的麻烦。

我有以下对象:

public class Foo
{
    public int FooId {get; set; }

    public int Bar {get; set; }

    /// <summary>
    /// Contains list of FooId
    /// </summary>
    public int[] Stackability
}

我需要做的是根据Foo找到Stackability的所有可能分组(即:可堆叠列表中的公共FooId),然后选择具有最高总和Bar

所以,例如:我的Ios为1,2和3的Foos。

+-------+-----+--------------+  
| FooId | Bar | Stackability |  
+-------+-----+--------------+  
| 1     | 5   | 2, 3         |  
+-------+-----+--------------+  
| 2     | 2   | 1, 3         |  
+-------+-----+--------------+  
| 3     | 6   | 1            |  
+-------+-----+--------------+  
  • Foo 1的Stackability包含值2和3,条形码为5。
  • Foo 2的可堆叠性包含值1和3,条形码为2。
  • Foo 3的Stackability包含值1,条形码为6。

在这个例子中,Foo 1可以与Foo 2和Foo 3堆叠,Foo 2可以与Foo 1和Foo 3堆叠,而Foo 3只能与Foo 1堆叠。

请注意,堆叠必须是倒数(因此即使Foo 2可以与Foo 1和Foo 3堆叠,Foo 3也只能与Foo 1堆叠,这意味着 Foo 2实际上只能堆叠Foo 1 )。

这将为我们提供以下分组及其Bar的相应总和:

  • {Foo 1,Foo 2} - Bar == 7
  • {Foo 1,Foo 3} - Bar == 11
  • {Foo 1} - Bar == 5
  • {Foo 2} - Bar == 2
  • {Foo 3} - Bar == 6

在这种情况下,正确的分组将是Foo 1和Foo 3.

提前致谢!

1 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,则以下内容将返回正确的分组。

void Main()
{
    var data = new[] {
        new Foo {FooId = 1, Bar = 5, Stackability = new int[] {2, 3} },
        new Foo {FooId = 2, Bar = 2, Stackability = new int[] {1, 3} },
        new Foo {FooId = 3, Bar = 6, Stackability = new int[] {1} } };

    var result = data
        .Select(d => new
        {
            Foo = d,
            Matches = data.Where(dm => dm.Stackability.Contains(d.FooId))
        })
        .Select(d => new
        {
            d.Foo,
            Narrowed = d.Matches.Where(m => d.Foo.Stackability.Contains(m.FooId))
        })
        .SelectMany(d => d.Narrowed.Select(n => new { Foos = new List<Int32> { d.Foo.FooId, n.FooId}, BarSum = d.Foo.Bar + n.Bar}))
        .OrderByDescending(d => d.BarSum)
        .First();

    Console.WriteLine($"{{ {String.Join(", ", result.Foos.Select(f => $"Foo {f}"))} }} - Bar == {result.BarSum}");
}

public class Foo
{
    public int FooId { get; set; }

    public int Bar { get; set; }

    /// <summary>
    /// Contains list of FooId
    /// </summary>
    public int[] Stackability { get; set; }
}

它返回以下内容:

  

{Foo 1,Foo 3}-酒吧== 11