Requirement: check if a list of successive words exists in a dataset. If it does, return a boolean to show the success.
Here is my code so far with unit tests (note this is sample code only - DataSet will be with Entity Framework not just a List):
[Test]
public void PhraseSearch()
{
var DataSet = new List<Word>
{
new Word { Text = "First", Sequence = 0 },
new Word { Text = "Second", Sequence = 1 },
new Word { Text = "Third", Sequence = 2 },
new Word { Text = "Forth", Sequence = 3 },
new Word { Text = "Five", Sequence = 4 }
};
var goodSearch = new string[]{ "First", "Second", "Third" };
var badSearch = new string[] { "First", "NOTFOUND", "Third" };
// successful test for 2 words
var result = DataSet.Any(wrd1 => wrd1.Text == goodSearch[0] && DataSet.Any(wrd2 => wrd2.Text == goodSearch[1] && wrd2.Sequence == wrd1.Sequence + 1));
Assert.That(result, Is.True);
result = DataSet.Any(wrd1 => wrd1.Text == badSearch[0] &&
DataSet.Any(wrd2 => wrd2.Text == badSearch[1] && wrd2.Sequence == wrd1.Sequence + 1));
// successful test for 2 words that don't match the data
Assert.That(result, Is.False);
// successful test for 3 words
result = DataSet.Any(wrd1 => wrd1.Text == goodSearch[0] &&
DataSet.Any(wrd2 => wrd2.Text == goodSearch[1] && wrd2.Sequence == wrd1.Sequence + 1 &&
DataSet.Any(wrd3 => wrd3.Text == goodSearch[2] && wrd3.Sequence == wrd2.Sequence + 1)));
Assert.That(result, Is.True);
// test for N words
result = .....
}
I want to expand the Linq code to do N words, but i'm not sure how to do this with Linq in Entity Framework, I'm leaning towards a hard coded method for each number of words but that seems really smelly.
You could use following extension which also takes into account that there could be multiple subsets in the longer sequence and a latter one contains the whole seb-sequence:
public static bool ContainsSequence<T>(this IEnumerable<T> seq, IEnumerable<T> subSeq, EqualityComparer<T> comparer = null)
{
if (comparer == null)
comparer = EqualityComparer<T>.Default;
IList<T> list = subSeq as IList<T> ?? new List<T>(subSeq);
IEnumerable<int> allIndexes = seq.AllIndexesOf(list.First(), comparer);
foreach (int index in allIndexes)
{
bool containsSequence = seq.Skip(index).Take(list.Count).SequenceEqual(list, comparer);
if (containsSequence)
return true;
}
return false;
}
Using this simple extension to find all indexes:
public static IEnumerable<int> AllIndexesOf<T>(this IEnumerable<T> seq, T itemToFind, EqualityComparer<T> comparer = null)
{
if (comparer == null)
comparer = EqualityComparer<T>.Default;
int index = 0;
foreach (T item in seq)
{
if (comparer.Equals(itemToFind, item))
yield return index;
index++;
}
}
Now the remaining check is simple:
bool containsSubseq = DataSet.OrderBy(x => x.Sequence).Select(x => x.Text)
.ContainsSequence(goodSearch);
However, this works for Linq-To-Objects not for database driven LINQ providers(saw too late).
I like the subset queries, but i ended up writing a recursive any statement to solve this as below:
public void PhraseSearch()
{
var DataSet = new List<Word>
{
new Word { Text = "First", Sequence = 0 },
new Word { Text = "Second", Sequence = 1 },
new Word { Text = "Third", Sequence = 2 },
new Word { Text = "Forth", Sequence = 3 },
new Word { Text = "Five", Sequence = 4 }
};
var goodSearch1 = new[] { "Second" };
var goodSearch2 = new[] { "First", "Second"};
var goodSearch3 = new[] { "Second", "Third", "Forth" };
var badSearch = new[] { "First", "NOTFOUND", "Third" };
// successful test for 1 word
int idxTosearch = 0;
var result = DataSet.Any(wrd => wrd.Text == goodSearch1[idxTosearch] && NextAny(goodSearch1,idxTosearch + 1,DataSet, wrd));
Assert.That(result, Is.True);
//reset counter
idxTosearch = 0;
result = DataSet.Any(wrd => wrd.Text == goodSearch2[0] && NextAny(goodSearch2, idxTosearch + 1, DataSet, wrd));
// successful test for 2 words
Assert.That(result, Is.True);
//reset counter
idxTosearch = 0;
// successful test for 3 words
result = DataSet.Any(wrd => wrd.Text == goodSearch3[0] && NextAny(goodSearch3, idxTosearch + 1, DataSet, wrd));
Assert.That(result, Is.True);
// test for bad words
//reset counter
idxTosearch = 0;
result = DataSet.Any(wrd => wrd.Text == badSearch[0] && NextAny(badSearch, idxTosearch + 1, DataSet, wrd));
Assert.That(result, Is.False);
}
private static bool NextAny(string[] phraseArray, int idxToSearch, List<Word> DataSet, Word previousWord)
{
if (idxToSearch == phraseArray.Length)
{
return true;
}
return allMatches.Any(wrd => wrd.Text == phraseArray[idxToSearch] && wrd.Sequence == previousWord.Sequence + 1 && NextAny(phraseArray, idxToSearch + 1, DataSet, wrd));
}
Try this to find a subset:
public void PhraseSearch()
{
var dataSet = new[] { "First", "Second", "Third", "Forth", "Five", };
var goodSearch = new[] { "First", "Second", "Third" };
var badSearch = new[] { "First", "NOTFOUND", "Third" };
Console.WriteLine(SubsequenceMatch(dataSet, new[] { "First", "Second", "Third" }));
Console.WriteLine(SubsequenceMatch(dataSet, new[] { "First", "NOTFOUND", "Third" }));
Console.WriteLine(SubsequenceMatch(dataSet, new[] { "Second", "Third", "Forth" }));
Console.WriteLine(SubsequenceMatch(dataSet, new[] { "Second", "Third", "Forth", "Five" }));
}
public bool SubsequenceMatch<T>(T[] source, T[] match)
{
return
Enumerable
.Range(0, source.Count() - match.Count() + 1)
.Any(n => source.Skip(n).Take(match.Count()).SequenceEqual(match));
}
This gives:
True
False
True
True
Related
List<string> OngoingClass = new List<String>()
{
"FLEXI","RETAIL","LITE","RTSPL"
};
List<string> ReturnClass = new List<String>()
{
"FLEXI","LITE","RETAIL","RTSPL"
};
Need to Combine those Two List with Certain Conditions.
1 . OngoingClass FLEXI Should Combine with ReturnClass FLEXI - Should not combine with rest of the classes.
2. Same way LITE fare should combine with LITE Fare.
3. Rest of the classes can combine each other.
For Example Result would like
{ "FLEXI" , "FLEXI" }
{ "LITE","LITE"}
{ "RETAIL","RETAIL"}
{ "RETAIL","RTSPL"}
{ "RTSPL","RETAIL"}
{ "RTSPL","RETAIL"}
As I said in comments, There could be better algorithms to get some combinations, but fo this small dataset this will do the trick
List<Tuple<string, string>> resultSequence = new List<Tuple<string, string>>();
OngoingClass.ForEach( item =>
{
ReturnClass.ForEach( item2 =>
{
if ((item == item2 && item2 == "FLEXI") || (item == item2 && item2 == "LITE") || ( item != "FLEXI" && item != "LITE" && item2 != "FLEXI" && item2 != "LITE"))
{
resultSequence.Add( new Tuple<string, string> ( item, item2 ));
}
});
});
Show result
foreach (var item in resultSequence)
{
Console.WriteLine(item);
}
This works for me:
var OngoingClass = new List<String>() { "FLEXI", "RETAIL", "LITE", "RTSPL" };
var ReturnClass = new List<String>() { "FLEXI", "LITE", "RETAIL", "RTSPL" };
var SpecialClass = new List<String>() { "FLEXI", "LITE" };
var query =
from o in OngoingClass
from r in ReturnClass
where (SpecialClass.Contains(o) && r == o)
|| (!SpecialClass.Contains(o) && !SpecialClass.Contains(r))
select (o, r);
This allows any values to be "special" and only pair with themselves.
I get this result:
Here is an approach that serves the purpose if you don't need/want duplicates. The "special" matches and other matches are aggregated separately, before the results are concatenated into a list of tuples (List<(string, string)>).
var OngoingClass = new List<String>() { "FLEXI","RETAIL","LITE","RTSPL" };
var ReturnClass = new List<String>() { "FLEXI","LITE","RETAIL","RTSPL" };
var SpecialClass = new List<String> { "FLEXI", "LITE" };
var SpecialResult =
OngoingClass.Intersect(ReturnClass).Intersect(SpecialClass)
.Select(special => (special, special));
var OtherResult =
OngoingClass.Except(SpecialClass)
.SelectMany(ongoing => ReturnClass.Except(SpecialClass)
.Select(ret => (ongoing, ret)));
var Result = SpecialResult.Concat(OtherResult).ToList();
Result:
[0]: ("FLEXI", "FLEXI")
[1]: ("LITE", "LITE")
[2]: ("RETAIL", "RETAIL")
[3]: ("RETAIL", "RTSPL")
[4]: ("RTSPL", "RETAIL")
[5]: ("RTSPL", "RTSPL")
Try following :
List<string> OngoingClass = new List<String>() { "FLEXI","LITE","RETAIL","RTSPL"};
List<string> ReturnClass = new List<String>() { "FLEXI","LITE","RETAIL","RTSPL"}
var results = OngoingClass.Select((x,i) => new object[] { x, ReturnClass[i]}).ToArray();
Here's a list, think of it as rows and columns where rows are going down and columns are side ways. the column count will always be the same for all rows.
var dataValues = new List<List<string>>()
{
//row 1
new List<string>(){"A","12","X","P8" },
//row 2
new List<string>(){"B","13","Y","P7" },
//row 3
new List<string>(){"C","12","Y","P6" },
//row 4
new List<string>(){"A","14","X","P5" },
//....
new List<string>(){"D","15","Z","P4" },
new List<string>(){"A","13","X","P3" },
new List<string>(){"B","14","Y","P2" },
new List<string>(){"C","13","Z","P1" },
};
The user providers a list of indexes to group by.
var userParam= new List<int>() { 0, 2 };
my question is how do i dynamically group dataValues by the userParam where user param is n amount of index. In the example above it will gorup by the first column and the 3rd. However the index can change and the amount of indexes can change aswell
example
var userParam2 = new List<int>() { 0, 2};
var userParam3 = new List<int>() { 0};
var userParam4 = new List<int>() { 0,1,2};
i know how to group by when i know how many indexes there will be (the the case below it's 2 index parameters), however when it's dynamic (x amount) then i do not know how to do this
var result = dataValues.GroupBy(e => new { G1 = e[userParam2 [0]], G2 = e[userParam2 [1]] });
You could use a Custom Comparer to achieve this :
1 - Declaration of GroupByComparer that inherit from IEqualityComparer :
public class GroupByComparer : IEqualityComparer<List<string>>
{
private static List<int> _intList;
public GroupByComparer(List<int> intList)
{
_intList = intList;
}
public bool Equals(List<string> x, List<string> y)
{
foreach (int item in _intList)
{
if (x[item] != y[item])
return false;
}
return true;
}
public int GetHashCode(List<string> obj)
{
int hashCode = 0;
foreach (int item in _intList)
{
hashCode ^= obj[item].GetHashCode() + item;
}
return hashCode;
}
}
2 - Call group by with EqualityComparer like :
var userParam = new List<int>() { 0, 2 };
var result = dataValues.GroupBy(e => e, new GroupByComparer(userParam));
I hope you find this helpful.
I believe i have something but this looks slow please let me know if there is anyway better of doing this.
var userParams = new List<int>() { 0, 2 };
var dataValues = new List<List<string>>()
{
new List<string>(){"A","12","X","P8" },
new List<string>(){"B","13","Y","P7" },
new List<string>(){"C","12","Y","P6" },
new List<string>(){"A","14","X","P5" },
new List<string>(){"D","15","Z","P4" },
new List<string>(){"A","13","X","P3" },
new List<string>(){"B","14","Y","P2" },
new List<string>(){"C","13","Z","P1" },
};
var result = new List<(List<string> Key, List<List<string>> Values)>();
result.Add((new List<string>(), dataValues));
for (int index = 0; index < userParams.Count; index++)
{
var currentResult = new List<(List<string> Key, List<List<string>> Values)>();
foreach (var item in result)
{
foreach (var newGroup in item.Values.GroupBy(e => e[userParams[index]]))
{
var newKey = item.Key.ToList();
newKey.Add(newGroup.Key);
currentResult.Add((newKey, newGroup.ToList()));
}
}
result = currentResult;
}
foreach(var res in result)
{
Console.WriteLine($"Key: {string.Join(#"\", res.Key)}, Values: {string.Join(" | ", res.Values.Select(e=> string.Join(",",e)))}");
}
final result
Key: A\X, Values: A,12,X,P8 | A,14,X,P5 | A,13,X,P3
Key: B\Y, Values: B,13,Y,P7 | B,14,Y,P2
Key: C\Y, Values: C,12,Y,P6
Key: C\Z, Values: C,13,Z,P1
Key: D\Z, Values: D,15,Z,P4
I realize my title probably isn't very clear so here's an example:
I have a list of objects with two properties, A and B.
public class Item
{
public int A { get; set; }
public int B { get; set; }
}
var list = new List<Item>
{
new Item() { A = 0, B = 0 },
new Item() { A = 0, B = 1 },
new Item() { A = 1, B = 0 },
new Item() { A = 2, B = 0 },
new Item() { A = 2, B = 1 },
new Item() { A = 2, B = 2 },
new Item() { A = 3, B = 0 },
new Item() { A = 3, B = 1 },
}
Using LINQ, what's the most elegant way to collapse all the A = 2 items into the first A = 2 item and return along with all the other items? This would be the expected result.
var list = new List<Item>
{
new Item() { A = 0, B = 0 },
new Item() { A = 0, B = 1 },
new Item() { A = 1, B = 0 },
new Item() { A = 2, B = 0 },
new Item() { A = 3, B = 0 },
new Item() { A = 3, B = 1 },
}
I'm not a LINQ expert and already have a "manual" solution but I really like the expressiveness of LINQ and was curious to see if it could be done better.
How about:
var collapsed = list.GroupBy(i => i.A)
.SelectMany(g => g.Key == 2 ? g.Take(1) : g);
The idea is to first group them by A and then select those again (flattening it with .SelectMany) but in the case of the Key being the one we want to collapse, we just take the first entry with Take(1).
One way you can accomplish this is with GroupBy. Group the items by A, and use a SelectMany to project each group into a flat list again. In the SelectMany, check if A is 2 and if so Take(1), otherwise return all results for that group. We're using Take instead of First because the result has to be IEnumerable.
var grouped = list.GroupBy(g => g.A);
var collapsed = grouped.SelectMany(g =>
{
if (g.Key == 2)
{
return g.Take(1);
}
return g;
});
One possible solution (if you insist on LINQ):
int a = 2;
var output = list.GroupBy(o => o.A == a ? a.ToString() : Guid.NewGuid().ToString())
.Select(g => g.First())
.ToList();
Group all items with A=2 into group with key equal to 2, but all other items will have unique group key (new guid), so you will have many groups having one item. Then from each group we take first item.
Yet another way:
var newlist = list.Where (l => l.A != 2 ).ToList();
newlist.Add( list.First (l => l.A == 2) );
An alternative to other answers based on GroupBy can be Aggregate:
// Aggregate lets iterate a sequence and accumulate a result (the first arg)
var list2 = list.Aggregate(new List<Item>(), (result, next) => {
// This will add the item in the source sequence either
// if A != 2 or, if it's A == 2, it will check that there's no A == 2
// already in the resulting sequence!
if(next.A != 2 || !result.Any(item => item.A == 2)) result.Add(next);
return result;
});
What about this:
list.RemoveAll(l => l.A == 2 && l != list.FirstOrDefault(i => i.A == 2));
if you whould like more efficient way it would be:
var first = list.FirstOrDefault(i => i.A == 2);
list.RemoveAll(l => l.A == 2 && l != first);
It need to sort a string array like this to a special format. Our Array is:
input1 = new string[12]{"Active1","12","mm","Active2","17","mm","Width","25","mil","Height","20","mil"}
and our desired sort list is:
sort = new string[6]{"Serial","Width","Height","Active1","Active2","Time"}
My valid format for output is this:
Output = [{Serial,null,null},{Width,25,mil},{Height,20,mil},{Active1,12,mm},{Active2,17,mm},{Time,null,null}]
It is necessary to set null value for data that don't exist in Input Array.
I'm using this code for my purpose:
var Output = (from i in Enumerable.Range(0, input.Length / 3)
let index = Array.IndexOf(sort, input[i * 3])
where index >= 0
select ne3w string[] { input[i * 3], input[i * 3 + 1] , input[i * 3 + 2]})
.OrderBy(a => Array.IndexOf(sort, a[0])).ToArray();
but it doesn't show the values that don't exist in input Array.
I would put this into a separate method:
private static IEnumerable<string[]> TransformInput(string[] input)
{
return from key in new[] { "Serial", "Width", "Height", "Active1", "Active2", "Time" }
let keyIndex = Array.IndexOf(input, key)
let hasData = keyIndex > 1
select new[]
{
key,
hasData ? input[keyIndex + 1] : null,
hasData ? input[keyIndex + 2] : null
};
}
And then use it as follows:
var input1 = new string[12]
{ "Active1", "12", "mm", "Active2", "17", "mm", "Width", "25", "mil", "Height", "20", "mil" };
var sorted = TransformInput(input1);
You can do it with the method below:
private string[][] Sort(string[] input)
{
List<string> inputList = new List<string> ();
inputList = input.ToList<string> ();
List<string[]> sortedList = new List<string[]> ();
string[] sort = new string[]{"Serial", "Width", "Height", "Active1", "Active2", "Time"};
foreach(string key in sort)
{
if (inputList.Contains<string> (key)) {
int i = inputList.IndexOf (key);
string[] t = new string[]{inputList[i],inputList[i+1],inputList[i+2]};
sortedList.Add (t);
}
else
{
string[] t = new string[]{key,null, null};
sortedList.Add (t);
}
}
return sortedList.ToArray<string[]> ();
}
Hope it help you out!
Given the two sets of input data:
var input1 = new string[12]
{
"Active1","12","mm",
"Active2","17","mm",
"Width","25","mil",
"Height","20","mil"
};
var sort = new string[6]
{
"Serial","Width","Height","Active1","Active2","Time"
};
This worked for me:
var lookup =
input1
.Select((x, n) => new { x, n })
.ToLookup(xn => xn.n / 3)
.ToLookup(
z => z.ElementAt(0).x,
z => z.Skip(1).Select(w => w.x));
var result =
sort
.Select(x =>
new [] { x }
.Concat(lookup[x].SelectMany(z => z))
.Concat(new string[] { null, null })
.Take(3)
.ToArray())
.ToArray();
I got this result:
Building on Nitesh, but removing the need to scan input repeatedly by using a dictionary
using System.Linq; //at top of file
private static string[][] TransformInput(string[] input)
{
var sortOrder = new[] { "Serial", "Width", "Height", "Active1", "Active2", "Time" };
//dictionary pointing words to position in input
var inputDict = Enumerable.Range(0, input.Length/3)
.Select(i => i*3).ToDictionary(i => input[i]);
//Try to read position from dictionary; return nulls if fail
return sortOrder.Select(x => {
int i;
return (inputDict.TryGetValue(x, out i))
? new[]{x, input[i+1], input[i+2]}
: new[]{x, null, null};
}).ToArray();
}
I think this code is good for your problem.
static List<string[]> SortedList(string[] input)
{
var sort = new string[6] { "Serial", "Width", "Height", "Active1", "Active2", "Time" };
List<string[]> output = new List<string[]>();
for (int i = 0; i < sort.Length; i++)
{
var findIndex = input.ToList().IndexOf(sort[i]);
if (findIndex != -1)
output.Add(new string[3]
{
input[findIndex],
input[findIndex + 1],
input[findIndex + 2]
});
else
output.Add(new string[3]
{
sort[i],
null,
null
});
}
return output;
}
And now you call that method:
var input = new string[12] { "Active1", "12", "mm", "Active2", "17", "mm", "Width", "25", "mil", "Height", "20", "mil" };
var output = SortedList(input);
I have an array of elements where the element has a Flagged boolean value.
1 flagged
2 not flagged
3 not flagged
4 flagged
5 not flagged
6 not flagged
7 not flagged
8 flagged
9 not flagged
I want to break it into arrays based on the flagged indicator
output >
array 1 {1,2,3}
array 2 {4,5,6,7}
array 3 {8,9}
Linq doesn't have an operator for this, but I've written an extension method that you may be able to use (in the process of submitting it to MoreLinq, which you should also check out):
Using the operator below, you would write:
var result =
items.Segment( (item,prevItem,idx) => item.Flagged )
.Select( seq => seq.ToArray() ) // converts each sequence to an array
.ToList();
Here's the code of the extension method:
public static IEnumerable<IEnumerable<T>> Segment<T>(IEnumerable<T> sequence, Func<T, T, int, bool> newSegmentIdentifier)
{
var index = -1;
using (var iter = sequence.GetEnumerator())
{
var segment = new List<T>();
var prevItem = default(T);
// ensure that the first item is always part
// of the first segment. This is an intentional
// behavior. Segmentation always begins with
// the second element in the sequence.
if (iter.MoveNext())
{
++index;
segment.Add(iter.Current);
prevItem = iter.Current;
}
while (iter.MoveNext())
{
++index;
// check if the item represents the start of a new segment
var isNewSegment = newSegmentIdentifier(iter.Current, prevItem, index);
prevItem = iter.Current;
if (!isNewSegment)
{
// if not a new segment, append and continue
segment.Add(iter.Current);
continue;
}
yield return segment; // yield the completed segment
// start a new segment...
segment = new List<T> { iter.Current };
}
// handle the case of the sequence ending before new segment is detected
if (segment.Count > 0)
yield return segment;
}
}
I had a similar problem with this, and solved it using GroupBy and closure.
//sample data
var arrayOfElements = new[] {
new { Id = 1, Flagged = true },
new { Id = 2, Flagged = false },
new { Id = 3, Flagged = false },
new { Id = 4, Flagged = true },
new { Id = 5, Flagged = false },
new { Id = 6, Flagged = false },
new { Id = 7, Flagged = false },
new { Id = 8, Flagged = true },
new { Id = 9, Flagged = false }
};
//this is the closure which will increase each time I see a flagged
int flagCounter = 0;
var query =
arrayOfElements.GroupBy(e =>
{
if (e.Flagged)
flagCounter++;
return flagCounter;
});
What it does is grouping on an int (flagCounter), which is increased each time a Flagged element is found.
Please note this won't work with AsParallel().
Testing the results:
foreach(var group in query)
{
Console.Write("\r\nGroup: ");
foreach (var element in group)
Console.Write(element.Id);
}
Outputs:
Group: 123
Group: 4567
Group: 89
Considering:
var arrayOfElements = new[] {
new { Id = 1, Flagged = true },
new { Id = 2, Flagged = false },
new { Id = 3, Flagged = false },
new { Id = 4, Flagged = true },
new { Id = 5, Flagged = false },
new { Id = 6, Flagged = false },
new { Id = 7, Flagged = false },
new { Id = 8, Flagged = true },
new { Id = 9, Flagged = false }
};
You can write:
var grouped =
from i in arrayOfElements
where i.Flagged
select
(new[] { i.Id })
.Union(arrayOfElements.Where(i2 => i2.Id > i.Id).TakeWhile(i2 => !i2.Flagged).Select(i2 => i2.Id))
.ToArray();
This works if your elements are ordered by the Id attribute. If they don't, you'll have to inject a Sequence on your original array, that should be easy to do with linq as well, so you'll get a sequence.
Also, a better alternative should be:
// for each flagged element, slice the array,
// starting on the flagged element until the next flagged element
var grouped =
from i in arrayOfElements
where i.Flagged
select
arrayOfElements
.SkipWhile(i2 => i2 != i)
.TakeWhile(i2 => i2 == i || !i2.Flagged)
.Select(i2 => i2.Id)
.ToArray();
Note that those answers are using pure linq.
I don't think LINQ is the right tool for this task. What about this:
public static List<List<T>> PartitionData<T>(T[] arr, Func<T, bool> flagSelector){
List<List<T>> output = new List<List<T>>();
List<T> partition = null;
bool first = true;
foreach(T obj in arr){
if(flagSelector(obj) || first){
partition = new List<T>();
output.Add(partition);
first = false;
}
partition.Add(obj);
}
return output;
}
A small example, with the Data from Fábio Batistas post:
var arrayOfElements = new[] {
new { Id = 1, Flagged = true },
new { Id = 2, Flagged = false },
new { Id = 3, Flagged = false },
new { Id = 4, Flagged = true },
new { Id = 5, Flagged = false },
new { Id = 6, Flagged = false },
new { Id = 7, Flagged = false },
new { Id = 8, Flagged = true },
new { Id = 9, Flagged = false }
};
var partitioned = PartitionData(arrayOfElements, x => x.Flagged);
I don't think LINQ is suited for this very well. It could be done with Aggregate() but I think you'd be better of just looping with a foreach() building up the result.