Как упростить это лямбда-выражение? - PullRequest
0 голосов
/ 15 октября 2018

У меня есть этот класс, который содержит массив 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 голосов
/ 15 октября 2018

Если у вас есть объект, содержащий список, вы можете разместить логику непосредственно на объекте.Хотя на самом деле нет никакой причины (которую вы указали) использовать массив, поэтому можно также сделать его списком.

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;
}

И , кажется, работает в примере DotNetFiddle :

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)

0 голосов
/ 15 октября 2018

Если порядок не имеет значения, просто проверьте, присутствуют ли все три значения в массиве (не беспокойтесь об использовании индекса для проверки позиции каждого целого числа):

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)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...