2010-02-25 10 views
7

Podstawowym rozwiązaniem będzie wyglądać następująco:Znalezienie Jeśli numer docelowy jest sumą dwóch liczb w tablicy poprzez 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; 
} 

Teraz jestem bardzo nowy LINQ, ale to, co napisałem tak daleko:

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

return false; 

teraz biegnę do problemu danej poniższym przykładzie:
Array: 1, 2, 4, 5, 8
docelowa: 16

Powinien wrócić z powrotem do wartości false, ale wychwytuje 16-8 = 8. Więc jak mam to zrobić, aby nie zauważyłem siebie w sprawdzaniu zawartości? Czy mogę utworzyć drugą tablicę za każdym razem w zapytaniu, które nie zawiera numeru, nad którym pracuję (rozwiązując w ten sposób problem)?

Z góry dziękuję.

Odpowiedz

5

Czy tego właśnie szukasz?

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

[Edytuj] ta zwraca mecze dwukrotnie i ignoruje sytuację, w której liczba jest powielany w tablicy. Nie można obsługiwać te sytuacje, używając wyrażeń składni, ponieważ nie można uzyskać dostępu do indeksu dopasowanej pozycji, ale można to zrobić tak:

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

Dopóki nie masz żadnych zer w swojej szyk.

[głębszego zastanowienia Edit]

Idealne rozwiązanie mix:

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

Nice :) Wydajesz się o wiele bardziej przebudzony niż jestem dziś rano +1 – leppie

+0

Jedna rzecz: Co zrobić, jeśli tablica zawiera dwie liczby, które są równe i będą sumować się do celu? Ex: Szereg zawierał 2 8, a cel 16. Poza tym twoje stwierdzenie było niesamowite i bardzo mi pomogło. –

+0

Tak, również zwraca dwa pasujące pary dwa razy: tj. 4 + 8 = 12; 8 + 4 = 12. Próbuję tylko znaleźć lepszą odpowiedź. – pdr

1

Aby poprawić post PDR i rozwiać obaw wymienionych w komentarzach można użyć overloaded Select method porównać wskaźniki pozycji i zapewnia wyjątkowość.

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

Albo w notacji dot:

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); 
4

Co bym zrobił, aby rozwiązać ten problem w ogóle jest najpierw napisać "Chooser".

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

Wyjście selektora to sekwencja sekwencji. Każda pod-sekwencja ma długość num i składa się z elementów wybranych z oryginalnej sekwencji. Więc jeśli minął {10, 30, 20, 50} jako sekwencja i 3 dla num, to by dostać kolejność sekwencji:

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

wyniku.

Po wpisaniu Chooser, problem staje się łatwe:

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

I teraz można rozwiązać problem dla podciągów innych wymiarach, nie tylko parami.

Pisanie Chooser jest nieco trudne, ale nie jest też trudne .

Powiązane problemy