tags:

views:

140

answers:

3

Hello I am new to Linq , I found this thread which explain 90% of what I need http://stackoverflow.com/questions/2331882?tab=newest#tab-top , thanks "pdr"

but what I need is to get the Indices too , here is my modification I get the index of the first number but I don't know how to get the index of the second number

         int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var result = from item in numbers.Select((n1, idx) =>
             new { n1,idx, shortList = numbers.Take(idx) })
                     from n2 in item.shortList
                     where item.n1 + n2 == 7
                     select new { nx1 = item.n1,index1=item.idx, nx2=n2  };
+1  A: 

This will give you a pair of items, each of which containing a value from the array and its index. The pairs are limited to where the sums of the values equal a target. The && on the where clause eliminates duplicates and self-matching (applicable for even targets).

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int target = 7;

var query = from item1 in numbers.Select((number, index) => new { Number = number, Index = index })
            from item2 in numbers.Select((number, index) => new { Number = number, Index = index })
            where item1.Number + item2.Number == target
            && item1.Index < item2.Index
            select new { Item1 = item1, Item2 = item2 };

foreach (var itemPair in query)
{
    Console.WriteLine("{0}:{1}\t{2}:{3}",
        itemPair.Item1.Index,
        itemPair.Item1.Number,
        itemPair.Item2.Index,
        itemPair.Item2.Number);
}
Anthony Pegram
A: 

If it's definitely over an array then you can just do:

var result = from index1 in Enumerable.Range(0, numbers.Length)
             from index2 in Enumerable.Range(index1 + 1,
                                             numbers.Length - index - 1)
             where numbers[index1] + numbers[index2] == targetNumber
             select new { index1, index2, 
                          value1 = numbers[index1], value2 = numbers[index2] };

Otherwise, you can use the Select form that includes the index twice:

var result = from pair1 in numbers.Select((value, index) => new { value, index})
             from pair2 in numbers.Skip(pair1.index + 1)
                                  .Select((value, index) => 
                                   new { value, index = index - pair2.index - 1})
             where pair1.value + pair2.value == targetNumber
             select new { index1 = pair1.index, index2 = pair2.index,
                          value1 = pair1.value, value2 = pair2.value };

Both of these are really ugly though...

Jon Skeet
I have found that neither of these code snippets return the expected results on his original array and target. The first throws an `IndexOutOfRangeException`, while the second does not return the right indices. Neither snippet is going to return the element values to go along with indices.
Anthony Pegram
@Anthony: Oops - will fix both. It's extremely easy to get the element values as well.
Jon Skeet
+1  A: 

SelectMany is what you need ...

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int target = 7;

var query = numbers
              .SelectMany((num1,j) => numbers.Select((num2,i) => new {n1=num1, n2=num2, i=i, j=j}))
              .Where(x => x.n1 + x.n2 == target && x.i < x.j);

foreach (var x in query)        
   Console.WriteLine(x.n1 + " and " + x.n2 + " occur at " + x.i + "," + x.j );
Hightechrider
This is, of course, O(n squared). There is an O(n) algorithm to solve this (if they are sorted) - essentially a diagonal walk across the matrix - but implementing that in a purely functional way in LINQ would require some pretty cunning use of Aggregate().
Hightechrider
thanks really Linq is so powerful , what is your advise to master it.
Dr.H
That sounds like a new question :-) Advice on mastering it ... 1. Use it often; 2. Look at every foreach loop to see if it would be clearer / easier expressed in LINQ; 3. Follow the LINQ tag on StackOverflow to see all the questions people ask and the 'right' answers to them.
Hightechrider