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;
}
你实际上是在谈论SQL,还是数组?换句话说,你是在使用LINQ to SQL还是LINQ to Objects? LINQ to Objects操作符实际上并不改变它们的原始数据源--它们构建由数据源有效支持的序列。唯一改变顺序的操作是OrderBy/OrderByDescending/ThenBy/ThenByDescending --即使这样,这些操作对于相同顺序的元素也是稳定的。当然,许多操作会过滤掉一些元素,但返回的元素将处于相同的顺序。 如果你转换成一个不同的数据结构,例如ToLookup或ToDictionary,我不认为在这一点上顺序是保持的--但无论如何这是有些不同的(我相信Map到同一个键的值的顺序是为了查找而保持的)。
我在一个类似的问题中找到了一个很好的答案,这个问题引用了官方文件。 对于Enumerable方法(LINQ to Objects,适用于List<T>),您可以依赖Select、Where或GroupBy返回的元素的顺序,但对于ToDictionary或Distinct等本质上无序的对象,情况并非如此。
//original sorting order lost
var inv2 = db.Inventories
.GroupBy(l => l.VendorFullSKU)
.Select(cl => new Inventory2
{
VariantID = cl.FirstOrDefault() == null ? 0 : cl.FirstOrDefault().VariantID,
Quan = cl.Sum(c => c.Quan),
Color = cl.FirstOrDefault() == null ? "" : cl.FirstOrDefault().Color
});
//original sorting order restored
var bl = (from pv in db.ProductVariants
join inv in inv2 on pv.VariantID equals inv.VariantID
orderby inv.VariantID, inv.Color //sort
select inv.Color
).ToList();
//remove duplicates while preserving original sort order
var colorsDistinct = new List<string>();
foreach (var item in bl)
{
if (!colorsDistinct.Contains(item))
colorsDistinct.Add(item);
}
7条答案
按热度按时间ia2d9nvy1#
我检查了System.Linq.Enumerable的方法,丢弃了所有返回非IEnumerable结果的方法,并检查了每个方法的注解,以确定结果的顺序与源代码的顺序有何不同。
绝对保持顺序。可以按索引将源元素Map到结果元素
保留顺序。过滤或添加元素,但不重新排序。
破坏秩序--我们不知道预期的结果是什么。
显式重新定义顺序-使用这些选项更改结果的顺序
根据某些规则重新定义Order。
编辑:基于这个implementation,我已经将Distinct移到了Preserving order。
py49o6xq2#
你实际上是在谈论SQL,还是数组?换句话说,你是在使用LINQ to SQL还是LINQ to Objects?
LINQ to Objects操作符实际上并不改变它们的原始数据源--它们构建由数据源有效支持的序列。唯一改变顺序的操作是OrderBy/OrderByDescending/ThenBy/ThenByDescending --即使这样,这些操作对于相同顺序的元素也是稳定的。当然,许多操作会过滤掉一些元素,但返回的元素将处于相同的顺序。
如果你转换成一个不同的数据结构,例如ToLookup或ToDictionary,我不认为在这一点上顺序是保持的--但无论如何这是有些不同的(我相信Map到同一个键的值的顺序是为了查找而保持的)。
pw9qyyiw3#
如果您正在处理一个数组,听起来像是在使用LINQ-to-Objects,而不是SQL;大多数LINQ操作不会重新排序任何东西(输出的顺序与输入的顺序相同)-所以不要应用其他排序(OrderBy[Descending]/ThenBy[Descending])。
[edit:正如乔恩说得更清楚;LINQ通常会创建一个 * 新 * 序列,而不处理原始数据]
请注意,将数据推入
Dictionary<,>
(ToDictionary)将打乱数据,因为Dictionary不考虑任何特定的排序顺序。但最常见的事情(选择,在哪里,跳过,采取)应该是好的。
eyh26e7m4#
我在一个类似的问题中找到了一个很好的答案,这个问题引用了官方文件。
对于
Enumerable
方法(LINQ to Objects,适用于List<T>
),您可以依赖Select
、Where
或GroupBy
返回的元素的顺序,但对于ToDictionary
或Distinct
等本质上无序的对象,情况并非如此。来自Enumerable.GroupBy文档:
IGrouping<TKey, TElement>
对象的生成顺序基于源中生成每个IGrouping<TKey, TElement>
的第一个键的元素的顺序。分组中的元素按照它们在source
中出现的顺序生成。对于
IQueryable
扩展方法(其他LINQ提供程序)不一定如此。源代码:LINQ的可枚举方法是否保持元素的相对顺序?
vaqhlq815#
任何“分组依据”或“排序依据”都可能更改顺序。
but5z9lq6#
这里的问题特指LINQ-to-Objects。
如果您使用LINQ-to-SQL,则没有顺序,除非您使用以下内容强制执行:
如果您不使用LINQ-to-SQL执行此操作,则结果的顺序在后续查询之间可能会有所不同,即使是相同的数据,这可能会导致间歇性错误。
des4xlb07#
对我来说,问题是确定默认的排序顺序,结果是按2列排序,如下所示。经过多次迭代,我能够找到默认的排序顺序,并在我的LINQ查询中重做它。为了删除重复项,使用一个简单的foreach来创建一个没有重复项的新字符串列表。