【发布时间】:2014-06-24 21:26:35
【问题描述】:
什么是基于 LINQ 的函数,它将所有满足谓词的项放在序列的前面,例如 C++ 的 std::partition?
【问题讨论】:
标签: c# linq partitioning stl-algorithm
什么是基于 LINQ 的函数,它将所有满足谓词的项放在序列的前面,例如 C++ 的 std::partition?
【问题讨论】:
标签: c# linq partitioning stl-algorithm
如果我理解您想要实现的目标,更简单的解决方案是OrderByDescending:
IEnumerable<T> Partition<T>(IEnumerable<T> s, Func<T, bool> predicate)
{
return s.OrderByDescending(predicate);
}
这是因为bool 实现了IComparable<bool>,而false 在true 之前。因此,predicate 计算结果为 true 的项目将首先放在结果集中。
这是一个手工制作的实现,以防您有兴趣。我没有做过任何基准测试,但这个实际上可能更快。1
IEnumerable<T> Partition<T>(IEnumerable<T> s, Func<T, bool> predicate)
{
List<T> falses = new List<T>();
foreach(var t in s)
{
if (predicate(t))
{
yield return t;
}
else
{
falses.Add(t);
}
}
foreach (var t in falses)
{
yield return t;
}
}
1:手工解法是O(n),但是OrderBy被认为是O(n log n)。但是,根据OrderBy 方法的实现细节,它们的执行可能几乎相同。
【讨论】:
OrderByDescending 将被推迟。我肯定会支持OrderByDescending 解决方案,但只要马特意识到与他的实施的这种差异。
我的最佳选择:
IEnumerable<T> Partition<T>(IEnumerable<T> s, Func<T, bool> predicate)
{
var split = s.GroupBy(predicate);
return split
.Where(kv => kv.Key)
.Single()
.Concat(split
.Where(kv => !kv.Key)
.Single());
}
【讨论】:
使用SelectMany,您可以改进自己的答案:
IEnumerable<T> Partition<T>(IEnumerable<T> s, Func<T, bool> predicate)
{
return s.GroupBy(predicate).SelectMany(xs => xs);
}
【讨论】:
OrderBy。