Нахождение, является ли целевое число суммой двух чисел в массиве через LINQ

Основное решение было бы похоже на это:

bool sortTest(int[] numbers, int target)
{
    Array.Sort(numbers);
    for(int i = 0; i < numbers.Length; i++)
    {
       for(int j = numbers.Length-1; j > i; j--)
       {
           if(numbers[i] + numbers[j] == target)
               return true;
       }
    }
    return false;
}

Теперь я очень плохо знаком с LINQ, но это - то, что я записал до сих пор:

var result = from num in numbers
             where numbers.Contains(target -num)
             select num;
if (result.Count() > 0)
    return true;

return false;

Теперь я сталкиваюсь с проблемой, учитывая следующий пример:
Массив: 1, 2, 4, 5, 8
Цель: 16

Это должно возвратить назад false, но это ловит 16-8=8. Таким образом, как я иду о не разрешении, оно заметить себя в содержит проверку? Или я могу сделать второй массив каждым разом в запросе, который не содержит число, я работаю с (таким образом решение проблемы)?

Заранее спасибо.

7
задан 25 February 2010 в 05:38
поделиться

3 ответа

Это то, что вы? ищете?

var result = from n1 in numbers
             from n2 in numbers
             where n1 != n2 && n1 + n2 == target
             select new { n1, n2 };

[Edit] Это возвращает совпадения дважды и игнорирует ситуацию, когда число дублируется в массиве. Вы не можете справиться с этими ситуациями, используя синтаксис выражений, потому что вы не можете получить доступ к индексу совпадающего элемента, но вы можете сделать это следующим образом:

var result = numbers.Select((n1, idx) => 
    new {n1, n2 = numbers.Take(idx).FirstOrDefault(
    n2 => n1 + n2 == target)}).Where(pair => pair.n2 != 0);

Пока у вас нет нулей в вашем массиве.

[Дальнейшие размышления Редактировать]

Идеальное сочетание:

var result = from item in numbers.Select((n1, idx) =>
                 new {n1, shortList = numbers.Take(idx)})
             from n2 in item.shortList
             where item.n1 + n2 == target
             select new {n1 = item.n1, n2};
5
ответ дан 7 December 2019 в 01:19
поделиться

Чтобы улучшить ответ pdr и решить проблемы, упомянутые в комментариях, можно использовать перегруженный метод Select для сравнения индексов элементов и обеспечения уникальности.

public bool sortTest(int[] numbers, int target)
{
    var indexedInput = numbers.Select((n, i) => new { Number = n, Index = i });

    var result = from x in indexedInput
                 from y in indexedInput
                 where x.Index != y.Index
                 select x.Number + y.Number == target;

    return result.Any(item => item);
}

Или в точечной нотации:

var result = numbers.Select((n, i) => new { Number = n, Index = i })
                    .SelectMany(
                        x => indexedInput,
                        (x, y) => new { x = x,  y = y })
                    .Where(item => item.x.Index != item.y.Index)
                    .Select(item => item.x.Number + item.y.Number == target);
1
ответ дан 7 December 2019 в 01:19
поделиться

Что бы я сделал для решения этой проблемы в целом, это сначала напишу "селектор".

public static IEnumerable<IEnumerable<T>> Chooser<T>(this IList<T> sequence, int num)
{ ... left as an exercise ... }

Результатом выбора является последовательность последовательностей. Каждая подпоследовательность имеет длину num и состоит из элементов, выбранных из исходной последовательности. Таким образом, если вы передадите {10, 30, 20, 50} в качестве последовательности и 3 в качестве числа, в результате вы получите последовательность последовательностей:

{10, 30, 20}, {10, 30, 50}, {10, 20, 50}, {30, 20, 50}

.

После того, как вы написали Chooser, проблема становится простой:

var results = 
  from subsequence in numbers.Chooser(2)
  where subsequence.Sum() == target
  select subsequence;

И теперь вы можете решить проблему для подпоследовательностей других размеров, а не только для пар.

Написать Chooser немного сложно, но не слишком .

4
ответ дан 7 December 2019 в 01:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: