1

I have this sample code:

string[] digits = { "zero", "one", "two", "three", 
  "four", "five", "six", "seven", "eight", "nine" };

var shortDigits = digits.Where((digit, index) => digit.Length < index);

Console.WriteLine("Short digits:");
foreach (var d in shortDigits)
{
    Console.WriteLine("The word {0} is shorter than its value.", d);
}

Is there a way generating same output only by using LINQ expressions?

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
Ghita
  • 4,465
  • 4
  • 42
  • 69
  • You are only using Linq. Do what to print using linq as well? Or do you want a `from digit in digits` block ("query expressions")? – Kobi Jun 21 '11 at 10:29
  • Nope. In general, LINQ is for querying, not generating side-effects. (Of course there are plenty of ways that you can do it, but they'd be considered an abuse of LINQ, in my opinion.) – LukeH Jun 21 '11 at 10:30

5 Answers5

2

One long 1 liner

Console.WriteLine(
  string.Format("Short digits: \r\n{0}",
    string.Join(Environment.NewLine, 
        digits.Where((digit, index) => digit.Length < index)
              .Select(digit => 
                string.Format("The word {0} is shorter than its value.", digit))
                      .ToArray())));

Using some custom extension methods may ease the code. For example ToDelimeteredString()

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
DaveShaw
  • 52,123
  • 16
  • 112
  • 141
  • 1
    I *suspect* the OP wants to replace the `.Where((digit, index)` line with a query expression: `from digit, index in digits` (which isn't valid, just a sample). Can't be sure... – Kobi Jun 21 '11 at 10:39
  • ToDelimeteredString == string.Join http://msdn.microsoft.com/en-us/library/57a79xd0.aspx – Arnis Lapsa Jun 21 '11 at 11:17
  • yes, Kobi is right, not the side effects (the printing) was my intention te replace – Ghita Jun 21 '11 at 12:11
2

I understand you are referring only to var shortDigits = digits.Where((digit, index) => digit.Length < index); I would have to think hard why you'd want to create such a monster if you are referring to generating the whole output with only LINQ

You could do the following to get the same output:

int i = 0;
var shortDigits = from d in digits
                  where d.Length < i++
                  select d;
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • exactly this is what I wanted. I was trying to introduce the increment to i as a different statment there (possibly considering let statment) but I couldn't . I wonder if only this succint way of incrementing the i is possible ? – Ghita Jun 21 '11 at 12:08
  • @Ghita: You could also use `where d.Length < (i = i + 1)` wich is valid too. The problem is that it would get a little messier as you would have to initialize `i` to `-1` as you would first evaluate `i + 1` and then read `i` when executing the query. What I am pretty sure of is that there is no inbuilt way in `LINQ` of getting the index of `d` in `digits`. (of course you could always make `digits` a `List` and use `List.IndexOf(int)`). – InBetween Jun 21 '11 at 12:39
1

You cannot do this with LINQ (well, you can if you abuse it, but we don't want to go there) because LINQ is supposed to be free of side effects, and printing the numbers is most definitely a side effect (in the sense that it does not affect the numbers themselves).

However, you can get close enough with the List.ForEach method:

Console.WriteLine("Short digits:");

var shortDigits = digits.Where((digit, index) => digit.Length < index);
shortDigits.ToList().ForEach(d => 
    Console.WriteLine("The word {0} is shorter than its value.", d));
Jon
  • 428,835
  • 81
  • 738
  • 806
0

You can do something like that:

var output = digits.Where(
    (digit, index) => digit.Length < index).Select(d => 
      string.Format("The word {0} is shorter than its value.", d));

But at some point you still need a loop to display the results...

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
0

It is trivial to implement a Linq-like extension method that works like a foreach loop (see e.g. this question), but it has intentionally been left out of the Linq framework functions, because they are designed to be side-effect free. Therefore the way you are currently doing it is considered a better practice.

Community
  • 1
  • 1
Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46