如何简化此lambda表达式?

时间:2018-10-15 18:15:01

标签: c# lambda

我有一个包含int数组的类

 public class Combination
 {
    public int[] CombinationSet { get; set; }
 }

有一个静态列表,其中包含此类的许多实例

public static List<Combination> Combinations = new List<Combination>();

现在我需要一些方法来查找到目前为止我拥有的列表上的组合

2点

 public static List<Combination> FindCombinations(int x,int y)
    {
        if (x == y)
        {
            return Combinations.Where(
           lenght => lenght.CombinationSet.Length == 2)
           .Where( 
                data => (data.CombinationSet[0] == x && data.CombinationSet[1] == y)
               || (data.CombinationSet[1] == x && data.CombinationSet[0] == y)
               ).ToList();
        }
        else
        {
            return Combinations.Where(
          lenght => lenght.CombinationSet.Length == 2)
          .Where(data => data.CombinationSet.Contains(x)
          && data.CombinationSet.Contains(y)
          ).ToList();
        }

    }

示例: 如果列表包含集合:{1,2},{1,3},{1,2}

您将调用FindCombination(1,2),您将获得包含两个实例的列表

它工作正常,但是对于4个参数,else语句中将超过24行。我最多需要4个,我只是想知道是否还有一些更聪明的方法可以做到这一点。

对于3它看起来像这样

 public static List<Combination> FindCombinations(int x, int y,int z)
    {
        if(x == y || x == z || y == z)
        {
            return Combinations.Where(
            lenght =>
            lenght.CombinationSet.Length == 3).
            Where(
                inner => ( (
                    inner.CombinationSet[0] == x && inner.CombinationSet[1] == y && inner.CombinationSet[2] == z)
                || (inner.CombinationSet[0] == x && inner.CombinationSet[2] == y && inner.CombinationSet[1] == z)
                || (inner.CombinationSet[1] == x && inner.CombinationSet[0] == y && inner.CombinationSet[2] == z)
                || (inner.CombinationSet[1] == x && inner.CombinationSet[2] == y && inner.CombinationSet[0] == z)
                || (inner.CombinationSet[2] == x && inner.CombinationSet[0] == y && inner.CombinationSet[1] == z)
                || (inner.CombinationSet[2] == x && inner.CombinationSet[1] == y && inner.CombinationSet[0] == z)
                )).ToList();
        }
        else
        {
            return Combinations.Where(
            length =>
            length.CombinationSet.Length == 3
            ).Where(data => data.CombinationSet.Contains(x)
            && data.CombinationSet.Contains(y)
            && data.CombinationSet.Contains(z)
            ).ToList();
        }

    }

2 个答案:

答案 0 :(得分:2)

如果您有一个包含列表的对象,则可能需要将逻辑直接放在该对象上。尽管确实没有理由(您已提供)使用数组,但也可以将其设为列表。

public class Combination
{
    public List<int> CombinationSet { get; set; }

    public bool IsSequenceEqual(params int[] values)
    {
        return CombinationSet.SequenceEqual(values);
    }

    public override string ToString()
    {
        return string.Join(", ", CombinationSet);
    }
}

因此,每个组合都不在乎您传递多少参数,它只想确保顺序和项数相等。因此,将其扩展为功能:

public static List<Combination> FindCombinations(params int[] values)
{
    var result = _Combinations
        .Where(c => c.IsSequenceEqual(values))
        .ToList();

    return result;
}

还有seems to work in a DotNetFiddle example

public static void Main()
{
    _Combinations.Add(new Combination{ CombinationSet = new List<int>{ 1, 2, 3}});
    _Combinations.Add(new Combination{ CombinationSet = new List<int>{ 2, 3, 4}});
    _Combinations.Add(new Combination{ CombinationSet = new List<int>{ 3, 2, 1}});
    _Combinations.Add(new Combination{ CombinationSet = new List<int>{ 1, 2, 3}});

    Console.WriteLine("Test 1  (1,2,3)");
    foreach(var result in FindCombinations(1,2,3))
    {
        Console.WriteLine(result.ToString());
    }

    Console.WriteLine("Test 1  (3,2,1)");
    foreach(var result in FindCombinations(3,2,1))
    {
        Console.WriteLine(result.ToString());
    }

    Console.WriteLine("Test 1  (1,2)");
    foreach(var result in FindCombinations(1,2))
    {
        Console.WriteLine(result.ToString());
    }
}

导致:

  

测试1(1,2,3)

     

1、2、3

     

1、2、3

     

测试1(3,2,1)

     

3,2,1

     

测试1(1,2)

答案 1 :(得分:1)

如果顺序无关紧要,则只需检查数组中是否存在所有三个值(不必担心使用索引来检查每个整数的位置):

return Combinations.Where(c => c.CombinationSet.Contains(x) 
    && c.CombinationSet.Contains(y) 
    && c.CombinationSet.Contains(z));

如果必须确切地传入的元素数,则可以添加其他AND语句以匹配数组长度,等等。

编辑:根据您的评论,如果您在比较之前对整数进行排序,然后仅在排序的集合相同时才返回组合,该怎么办。只要组合必须包含传入的相同数量的元素,这应该起作用:

return Combinations.Where(c => c.CombinationSet.OrderBy(i => i).SequenceEqual(new int[] { x, y, z }.OrderBy(j => j)));