Reputation: 13209
Given a list of elements like so:
int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2,
6, 15, 32, -5, 6, 19, 22 };
Is there an easy way in Linq to do something along the lines of "Select the elements from the -1 up to the next negative number (or the list exhausts)"? A successful result for -1 would be (-1, 9, 8, 7, 6, 5, 4). Using -2 would give the result (-2, 6, 15, 32).
Not a homework problem. I'm just looking at an implementation using a bool
, a for
loop, and an if
wondering if there's a cleaner way to do it.
Upvotes: 9
Views: 10854
Reputation: 9511
var first = ia.Select((i, index) => new {i, index}).Where((i, index) => i.i == x).First();
var ind = first.index;
var second = ia.SkipWhile( (i, index) => index <= ind).TakeWhile(i => i > 0);
var ints = new[]{first.i}.Union(second);
Upvotes: 0
Reputation: 69290
Updated
This time I've tested the code... Using the two parameter form of TakeWhile we can force it to accept the first element (j == 0)
even when the test for i
is not satisfied.
ia.SkipWhile(i => i != -1).TakeWhile((i, j) => i >= 0 || j == 0)
TakeWhile(Func<int, int, bool>)
requires a function/lambda that takes two parameters. The first being the value to be tested, the second being the index of the element.
Upvotes: 5
Reputation: 73351
Does it have to be Linq? You can use Extensions methods to get a cleaner solution.
int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2,
6, 15, 32, -5, 6, 19, 22 };
// Call the Extension method
int[] results = ia.SelectRangeLoop(-2);
// Print Results
for (int i = 0; i < results.Length; i++)
{
Console.Write(" {0} ", results[i]);
}
The method for SelectRangeLoop is below.
public static int[] SelectRangeLoop(this int[] value, int startNumber)
{
List<int> results = new List<int>();
bool inNegative = false;
for (int i = 0; i < value.Length; i++)
{
if (value[i] == startNumber)
{
inNegative = true;
results.Add(value[i]);
continue;
}
if (inNegative && value[i] < 0)
{
break;
}
if (inNegative)
{
results.Add(value[i]);
}
}
return results.ToArray();
}
Upvotes: 0
Reputation: 23840
Take a look at the TakeWhile Linq extension method. Takes items from the list as long as the condition is true, skips the rest.
Example:
int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2,
6, 15, 32, -5, 6, 19, 22 };
var result = ia
.SkipWhile(i => i != -1)
.Skip(1)
.TakeWhile(i => i >= 0);
Note the Skip(1) after the SkipWhile. SkipWhile skips everything up to, but not including the matching element. TakeWhile then Takes items, up to but not including the matching element. Because -1 is not greater than or equal to zero, you get an empty result.
Upvotes: 11