说我有List<Point> { {5,2}, {7,2}, {3,9} }
我希望我的输出始终以具有最小X值的点开始
类似于:
var output = input.Rotate((x, y) => x.X < y.X));
output = `List<Point> { {3,9}, {5,2}, {7,2} }`
手动不难:
我只是想知道是否有LINQ方式这样做?
答案 0 :(得分:2)
首先找到最小X值:
var minX = input.Min(p => p.X);
接下来得到X是最小值的第一个出现位置:
var index = input.FindIndex(p => p.X == minX);
现在通过将原件分成两部分来创建一个新列表:
var newInput = input.Skip(index).Concat(input.Take(index));
答案 1 :(得分:1)
您无法一步完成,您需要至少两次遍历数组。但你可以这样做(有点hacky)方法:
var range = Enumerable.Range(0, list.Count);
var index = range.Aggregate((p,c) => list[p].X> list[c].X? c : p);
var rotated = range.Select(i => list[(i + index) % list.Count]).ToList();
这里是example(使用Tuple
而不是Point
,但它的原理是相同的)
第一步是找到数组中最低值的index
。第二步,他们从该索引开始构建你的新数组并循环。
如果你想将它封装在扩展方法中,你可以这样做:
public static IEnumerable<T> Rotate<T>(this List<T> list, Func<T,T, bool> comparer)
{
var range = Enumerable.Range(0, list.Count);
var index = range.Aggregate((p,c) => predicate(list[p],list[c]) ? p : c);
return range.Select(i => list[(i + index) % list.Count]);
}
您可以这样称呼:
var output = input.Rotate((x, y) => x.X < y.X));
您传入的函数如果评估为true,则会选择x
而不是y