Preserving order with LINQ
I examined the methods of System.Linq.Enumerable, discarding any that returned non-IEnumerable results. I checked the remarks of each to determine how the order of the result would differ from order of the source.
Preserves Order Absolutely. You can map a source element by index to a result element
- AsEnumerable
- Cast
- Concat
- Select
- ToArray
- ToList
Preserves Order. Elements are filtered or added, but not re-ordered.
- Distinct
- Except
- Intersect
- OfType
- Prepend (new in .net 4.7.1)
- Skip
- SkipWhile
- Take
- TakeWhile
- Where
- Zip (new in .net 4)
Destroys Order - we don't know what order to expect results in.
- ToDictionary
- ToLookup
Redefines Order Explicitly - use these to change the order of the result
- OrderBy
- OrderByDescending
- Reverse
- ThenBy
- ThenByDescending
Redefines Order according to some rules.
- GroupBy - The IGrouping objects are yielded in an order based on the order of the elements in source that produced the first key of each IGrouping. Elements in a grouping are yielded in the order they appear in source.
- GroupJoin - GroupJoin preserves the order of the elements of outer, and for each element of outer, the order of the matching elements from inner.
- Join - preserves the order of the elements of outer, and for each of these elements, the order of the matching elements of inner.
- SelectMany - for each element of source, selector is invoked and a sequence of values is returned.
- Union - When the object returned by this method is enumerated, Union enumerates first and second in that order and yields each element that has not already been yielded.
Edit: I've moved Distinct to Preserving order based on this implementation.
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Does Select linq function preserve List collection order?
.net is open sourced now. Check it out for IList
First()
just takes first element. And Select just enumerates list, so order is preserved.
As for your particular First(x => x.Item1)
case it will turn into.
foreach (TSource element in source) {
if (element.Item1) return element;
}
where source is similar to that IEnumberable (I've removed some code, which is not used in your case)
public Func<int, Tuple<bool, string>> Current {
get { return current; }
}
public override bool MoveNext() {
var enumerator = conditions.GetEnumerator();
while (enumerator.MoveNext()) {
Func<int, Tuple<bool, string>> item = enumerator.Current;
current = item(t);
return true;
}
return false;
}
Does Enumerable.Where in LINQ-to-objects preserve order?
Microsoft does actually document that LINQ to Objects preserves ordering. The document
http://msdn.microsoft.com/en-us/library/dd460677%28v=vs.110%29.aspx says
In PLINQ, the goal is to maximize performance while maintaining
correctness. A query should run as fast as possible but still produce
the correct results. In some cases, correctness requires the order of
the source sequence to be preserved; however, ordering can be
computationally expensive. Therefore, by default, PLINQ does not
preserve the order of the source sequence. In this regard, PLINQ
resembles LINQ to SQL, but is unlike LINQ to Objects, which does
preserve ordering.
As mentioned in this stackoverflow article microsoft documents for some LINQ methods that they do not preserve order. For example the documentation of distinct mentions that this method returns an unordered sequence.
Why LINQ Distinct() does not preserve order list?
Distinct() is about returning distinct rows, it doesn't promise any order but still orders on what it operates. For ordering there is OrderBy, OrderByDescending. In your case, since there is no Date in your final list, you cannot order by date.
EDIT:
void Main()
{
List<FarmDiary> farmDiary = new List<FarmDiary> {
new FarmDiary{Id=1, PersonInCharge="Bob",Date=new DateTime(2018,6,1)},
new FarmDiary{Id=2, PersonInCharge="John",Date=new DateTime(2018,6,2)},
new FarmDiary{Id=3, PersonInCharge="Bob",Date=new DateTime(2018,6,15)},
new FarmDiary{Id=4, PersonInCharge="David",Date=new DateTime(2018,7,1)},
new FarmDiary{Id=5, PersonInCharge="Zachary",Date=new DateTime(2018,6,10)},
};
List<string> staffNames = farmDiary
.GroupBy(d => d.PersonInCharge)
.OrderByDescending(x => x.OrderByDescending(d => d.Date).First().Date)
.Select(x => x.Key)
.ToList();
staffNames.Dump();
}
public class FarmDiary
{
public int Id { get; set; }
public string PersonInCharge { get; set; }
public DateTime Date { get; set; }
}
Preserve order with linq after groupby and selectmany
Yes, if you first select your DateList and combine it with an index, using an overload of .Select
that uses a delegate with a second (int
) parameter that is called with the index of the items from the sequence :
DateList
.Select((dateTime, idx) => new {dateTime, idx})
.GroupBy(x => x.dateTime.Date.Subtract(firstDay).Days / 7 + 1)
...and persist the value through the linq chain
.SelectMany(gx => gx, (gx, x) => new {Week = gx.Key,
DateTime = x.dateTime,
Count = gx.Count(),
x.idx})
...then use it to re-order the output
.OrderBy(x => x.idx)
...and strip it from your final selection
.Select(x => new {x.Week, x.DateTime, x.Count});
then you can maintain the same order as the original list.
Linq to Objects: does GroupBy preserve order of elements?
Found answer on MSDN: Yes.
The
IGrouping<TKey, TElement>
objects are yielded in an order based on the order of the elements in source that produced the first key of eachIGrouping<TKey, TElement>
. Elements in a grouping are yielded in the order they appear in source.
Retaining order with LINQ using .Contains
If I understand correctly, contentBasedFiltered
is the ordered list and you want the original items from restaurantsCloseToUser
but in the order they have in contentBasedFiltered
. So I'd try the following:
var test = contentBasedFiltered.Select(x => restaurantsCloseToUser.FirstOrDefault(r => r.Id == x.Id)).ToList();
This returns a list in order of contentBasedFiltered
but with the items from restaurantsCloseToUser
.
LINQ - Preserve order across objects with .Any()?
You need to do it the other way around:
Query orderedProjects
and select the corresponding items from projects
:
var projects =
orderedProjects
.Select(o => projects.SingleOrDefault(p => p.ProjectNbr == o.ProjectNbr))
.Where(x => x != null) // This is only necessary if there can be
// ProjectNbrs in orderedProjects that are not in
// projects
.ToList();
Does LINQ to Objects keep its order
In current .Net implementation it use such code. But there are no guarantee that this implementation will be in future.
private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
int index = -1;
foreach (TSource source1 in source)
{
checked { ++index; }
yield return selector(source1, index);
}
}
Retain default order for Linq Contains
Your assumption is wrong. SQL server is the one that is sending the results back in the order you are getting them. However, you can fix that:
var x = db.ItemTemplates.Where(a => a.MainGroupId == mnId)
.Where(a => a.SubGruopId == sbId)
.FirstOrDefault();
var ids = new List<int> { x.Atribute1, x.Atribute2, x.Atribute3, x.Atribute4 };
var y = db.Atributes.Where(a => ids.Contains(a.AtributeId))
.Select(g => new
{
Id = g.AtributeId,
Name = g.AtributeName,
AtType = g.AtributeType,
Options = g.atributeDetails
.Where(w=>w.AtributeDetailId!=null)
.Select(z => new
{
Value=z.AtributeDetailId,
Text=z.AtDetailVal
})
})
.ToList()
.OrderBy(z=>ids.IndexOf(z.Id));
Feel free to do another select after the orderby to create a new anonymous object without the Id if you absolutely need it to not contain the id.
PS. You might want to correct the spelling of Attribute, and you should be consistent in if you are going to prefix your property names, and how you do so. Your table prefixes everything with Atribute(sp?), and then when you go and cast into your anonymous object, you remove the prefix on all the properties except AtributeType
, which you prefix with At
. Pick one and stick with it, choose AtName, AtType, AtOptions or Name, Type, Options.
Related Topics
Data Binding to Selecteditem in a Wpf Treeview
Conditional Operator Cannot Cast Implicitly
Binding a Wpf Combobox to a Custom List
What Does the @ Symbol Before a Variable Name Mean in C#
C# Error: "An Object Reference Is Required For the Non-Static Field, Method, or Property"
Easier Way to Debug a Windows Service
Why Does C# Forbid Generic Attribute Types
Itextsharp - CSS Not Getting Applied - C# .Net
.Net Global Exception Handler in Console Application
Unity: Null While Making New Class Instance
How to Get Httpclient to Pass Credentials Along With the Request
Are String.Equals() and == Operator Really Same
How to Easily Check If Access Is Denied For a File in .Net
Why Catch and Rethrow an Exception in C#
Using C#, How Does One Figure Out What Process Locked a File