我正在编写一个带有一系列System.Windows.Point的函数,并返回一个ValueTuple,其中包含所有点的边界X和Y值。这是为了确定图轴的标签。
我试图将我执行的列表的迭代次数最小化为一次。经过大量的谷歌搜索,我已经适应(阅读:"复制")下面的方法,我被告知将这样做。但我不确定如何验证这一事实。我想知道是否有人更熟悉LINQ
我的LINQ-Fu还不强。
由于
/// <summary>
/// X and Y axis boundaries in the form of a System.ValueTuple.
/// </summary>
public (double MinX, double MaxX, double MinY, double MaxY)
GetBounds(List<System.Windows.Point> pts)
{
// Calculate the bounds with a LINQ statement. Is this one iteration or many?
var a = pts.GroupBy(i => 1).Select(
pp => new
{
MinY = pp.Min(p => p.Y),
MaxY = pp.Max(p => p.Y),
MinX = pp.Min(p => p.X),
MaxX = pp.Max(p => p.X)
}).FirstOrDefault();
return a != null ? (a.MinX, a.MaxX, a.MinY, a.MaxY) : (0, 0, 0, 0);
}
答案 0 :(得分:4)
确认以下功能确实只会迭代列表一次,即使它计算了4个不同的值
否 - 原始列表将有效地迭代4次。你正在创建一个&#34; null&#34;分组将包装原始集合,以便您可以&#34;项目&#34;集合到一个对象。因为你在&#34;分组&#34;上调用了4个linq函数。 - 原始列表将重复4次。它在功能上等同于:
foreach
如果这对您来说是个问题,找到边界的惯用方法是使用int MinX, MaxX, MinY, MaxY;
MaxX = MaxY = Int.MinValue;
MinX = MinY = Int.MaxValue;
foreach(Point p in pts)
{
MinX = Math.Min(p.X, MinX);
MaxX = Math.Max(p.X, MaxX);
MinY = Math.Min(p.Y, MinY);
MaxY = Math.Max(p.Y, MaxY);
}
var a = new
{
MinY,
MaxY,
MinX,
MaxX
};
循环并手动跟踪最小和最大x和y坐标。这将是一个相对较短的函数,并将迭代次数减少75%:
Aggregate
你可以使用var a = pts.Aggregate(
new {
MinX = int.MaxValue,
MaxX = int.MinValue,
MinY = int.MaxValue,
MaxY = int.MinValue
},
(acc, p) => new {
MinX = Math.Min(p.X, acc.MinX);
MaxX = Math.Max(p.X, acc.MaxX);
MinY = Math.Min(p.Y, acc.MinY);
MaxY = Math.Max(p.Y, acc.MaxY);
});
循环查找带有lambda的分钟和最大值:
import web
urls = {
'/', 'home',
'/register', 'registerclick'
}
render = web.template.render("views/templates", base="MainLayout")
app = web.application(urls, globals())
# Classes/Routes
class home:
def GET(self):
return render.home()
class registerclick:
def GET(self):
return render.register()
if __name__ == "__main__":
app.run()
但聚合器将为源集合中的每个对象创建一个对象,另外一个用于&#34; initial&#34;宾语。因此列表只会迭代一次,但会创建多个临时对象,从而增加了需要GC的内存量。