Reputation: 2370
How to perform this without iteration, with LINQ?
string[] flatSource = {"region1", "subregion1",
"region2", "sub1", "sub2",
"region3", "sub1", "sub2"};
string previousRegion = "";
foreach (var item in flatSource)
{
if (SomeRegionDictionary.Contains(item))
previousRegion = item; //This is what I can't figure out
else
yield return new SubregionWithRegion{Region = previousRegion, SubRegion = item};
}
Upvotes: 1
Views: 227
Reputation: 7681
You can do it in one statement with Zip in Net 4.0:
return
flatSource.Where(i=>SomeRegionDictionary.Contains(i)).Zip(arr.Skip(1),
(first, second) => new SubregionWithRegion{Region = first, SubRegion = second});
If you don't have Net 4.0, you can use this implementation: Zip Me Up
Upvotes: 1
Reputation: 45119
Seems that i didn't read the question carefully enough. So the extension below might be useful, but not to this question.
public static class IEnumerableOfTExtensions
{
public static T Before<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
if (source == null)
throw new ArgumentNullException("source");
if (condition == null)
throw new ArgumentNullException("condition");
using (var e = source.GetEnumerator())
{
var first = true;
var before = default(T);
while (e.MoveNext())
{
if (condition(e.Current))
{
if (first)
throw new ArgumentOutOfRangeException("condition", "The first element corresponds to the condition.");
return before;
}
first = false;
before = e.Current;
}
}
throw new ArgumentOutOfRangeException("condition", "No element corresponds to the condition.");
}
}
Upvotes: 2
Reputation: 113452
Your current solution is fine; LINQ isn't the ideal choice for such stateful queries. Here's a pure-LINQ solution though; it's not ideal because it is a little cryptic and has quadratic complexity, but is functionally equivalent:
return flatSource.Select((item, index) =>
new SubregionWithRegion
{
Region = flatSource.Take(index + 1)
.LastOrDefault(SomeRegionDictionary.ContainsKey) ?? "",
SubRegion = item
})
.Where(srwr => !SomeRegionDictionary.ContainsKey(srwr.SubRegion));
The stateful nature of the loop is handled with the Take
+ LastOrDefault
queries, and the tricky else
condition is handled by the final Where
clause.
Upvotes: 3