如何从控件数组中获得面积最小的控件?

时间:2018-09-02 16:18:36

标签: c# winforms linq

我有一系列控件:

Control[] controls = getControls();

我需要以最小的面积获得控件。我知道我可以像这样对它进行排序并获得索引0中的控制权:

var min = filtered.OrderBy(x => x.Height * x.Width).ToArray()[0]; 

但是如何在不订购控件的情况下获取它?

2 个答案:

答案 0 :(得分:2)

这可以通过非常强大但未充分利用的Aggregate方法来实现:

var min = controls.Aggregate((x, y) => x.Height * x.Width < y.Height * y.Width ? x : y);

您可以使用Control属性扩展Area类,以避免在Aggregate方法中重复乘法代码。

答案 1 :(得分:1)

您可以为此使用Enumerable.Aggregate。 that,该函数会一遍又一遍地计算出最小控件的大小。

If与创建所有linq函数类似,可以更有效(且更易于创建)创建扩展函数,该扩展函数接受Controls序列并返回最小的扩展函数。参见extension methods demystified

// extension function: gets the size of a control
public static int GetSize(this Control control)
{
    return (control.Height * control.Width);
}

// returns the smallest control, by size, or null if there isn't any control
public static Control SmallestControlOrDefault(this IEnumerable<Control> controls)
{
    if (controls == null || !controls.Any()) return null; // default

    Control smallestControl = controls.First();
    int smallestSize = smallestControl.GetSize();

    // check all other controls if they are smaller
    foreach (var control in controls.Skip(1))
    {
        int size = control.GetSize();
        if (size < smallestSize)
        {
             smallestControl = control;
             smallestSize = size;
        }
    }
    return smallestControl;
}

Skip(1)将再次遍历第一个元素。如果您不希望这样做,请使用GetEnumeratorMoveNext进行枚举:

var enumerator = controls.GetEnumerator();
if (enumerator.MoveNext())
{   // there is at least one control
    Control smallestControl = enumerator.Current;
    int smallestSize = smallestControl.GetSize();

    // continue enumerating the other controls, to see if they are smaller
    while (enumerator.MoveNext())
    {   // there are more controls
        Control control = enumerator.Current;
        int size = control.GetSize();
        if (size < smallestSize)
        {   // this control is smaller
            smallestControl = control;
            smallestSize = size;
        }
    }
    return smallestControl;
}
else
{   // empty sequence
    ...
}

这样,您绝对可以确定自己只会枚举一次

用法:

IEnumerable<Control> controls = ...
Control smallestControl = controls.SmallestControlOrDefault();