C# 我想从列表中找到最接近的较大纸张尺寸
我想从代码中显示的列表中找到最接近的相等或更大的纸张尺寸C# 我想从列表中找到最接近的较大纸张尺寸,c#,linq,C#,Linq,我想从代码中显示的列表中找到最接近的相等或更大的纸张尺寸 List<PaperSize> paper = new List<PaperSize>(); paper.Add(new PaperSize("B5", 516, 729)); paper.Add(new PaperSize("A5", 420, 595)); paper.Add(new PaperSize("A4", 595, 842)); paper.Add(new PaperSize("B4", 729,
List<PaperSize> paper = new List<PaperSize>();
paper.Add(new PaperSize("B5", 516, 729));
paper.Add(new PaperSize("A5", 420, 595));
paper.Add(new PaperSize("A4", 595, 842));
paper.Add(new PaperSize("B4", 729, 1032));
paper.Add(new PaperSize("A4L", 842, 595));
paper.Add(new PaperSize("A3", 1191, 842));
paper.Add(new PaperSize("A2", 1685, 1190));
paper.Add(new PaperSize("A1", 2384, 1685));
paper.Add(new PaperSize("A0", 3371, 2384));
int width = 1189;
int height = 840;
string name = paper.SkipWhile(p => p.PaperWidth < width && p.PaperHeight <
height).First().PaperName;
Console.WriteLine("Nearest equal or larger papersize is " + name);
如果我提供宽度1189和高度840,我希望选择纸张A3,但结果是A4。
我怎么还A3
编辑:事实上,列表并不总是以特定的方式排序。正因为如此,@Johnny和@Knoop的建议解决了我的问题。接下来,我忘了将PaperSize及其属性PaperName、PaperWidth和PaperHeight包括在内,但你们都正确地认为我有这个属性。将您的(&p)更改为| |。如果宽度或高度太小,则要跳过
string name = paper.SkipWhile(p => p.PaperWidth < width || p.PaperHeight <
height).First().PaperName;
还值得考虑的是,可能没有足够大的纸张尺寸。如果是这种情况,则将name设置为null
string name = paper
.FirstOrDefault(p => p.PaperWidth >= width && p.PaperHeight >= height)
?.PaperName;
当然,只有当您的纸张尺寸列表严格按面积排序时,这些才起作用,最小的排在第一位。如果不是这样,您可以选择浪费空间最小的纸张尺寸:
int area = width * height;
string name = paper
.Where(p => p.PaperWidth >= width && p.PaperHeight >= height)
.OrderBy(p => p.PaperWidth * p.PaperHeight - area)
.FirstOrDefault()
?.PaperName;
将&&更改为| |。如果宽度或高度太小,则要跳过
string name = paper.SkipWhile(p => p.PaperWidth < width || p.PaperHeight <
height).First().PaperName;
还值得考虑的是,可能没有足够大的纸张尺寸。如果是这种情况,则将name设置为null
string name = paper
.FirstOrDefault(p => p.PaperWidth >= width && p.PaperHeight >= height)
?.PaperName;
当然,只有当您的纸张尺寸列表严格按面积排序时,这些才起作用,最小的排在第一位。如果不是这样,您可以选择浪费空间最小的纸张尺寸:
int area = width * height;
string name = paper
.Where(p => p.PaperWidth >= width && p.PaperHeight >= height)
.OrderBy(p => p.PaperWidth * p.PaperHeight - area)
.FirstOrDefault()
?.PaperName;
尝试此操作,不应提前对纸张列表进行排序:
paper.Where(p => p.PaperWidth - width >= 0 && p.PaperHeight - height >= 0)
.OrderBy(p => p.PaperWidth - width + p.PaperHeight - height)
.FirstOrDefault();
尝试此操作,不应提前对纸张列表进行排序:
paper.Where(p => p.PaperWidth - width >= 0 && p.PaperHeight - height >= 0)
.OrderBy(p => p.PaperWidth - width + p.PaperHeight - height)
.FirstOrDefault();
要求:
给定宽度和高度,请给我大于此宽度和高度的最小纸张尺寸的名称
这有点棘手
假设宽度和高度分别为100和100。你有两份文件:
纸张尺寸A的宽度为105,高度为2000,
纸张尺寸B的宽度为110,高度为110。
两张纸都足够大。如果你首先看宽度,你会选择A纸,因为它的宽度最小。然而,B纸似乎比A纸小得多
所以首先你必须自己思考:什么时候一张纸比另一张纸小?。您需要一个PaperComparer类来实现IComparer:
在连接LINQ语句时,始终确保只有最后一个语句不返回IEnumerable
注:
此LINQ语句始终有效,即使在空的或未排序的AvailablePersizes集合上也是如此
如果将来您决定以不同的方式定义较小的纸张大小,则LINQ语句不必更改
优化
如果你只想要最小的,那么订购所有尺寸的纸张是相当浪费的。考虑使用最小纸张尺寸< /P>
要求:
给定宽度和高度,请给我大于此宽度和高度的最小纸张尺寸的名称
这有点棘手
假设宽度和高度分别为100和100。你有两份文件:
纸张尺寸A的宽度为105,高度为2000,
纸张尺寸B的宽度为110,高度为110。
两张纸都足够大。如果你首先看宽度,你会选择A纸,因为它的宽度最小。然而,B纸似乎比A纸小得多
所以首先你必须自己思考:什么时候一张纸比另一张纸小?。您需要一个PaperComparer类来实现IComparer:
在连接LINQ语句时,始终确保只有最后一个语句不返回IEnumerable
注:
此LINQ语句始终有效,即使在空的或未排序的AvailablePersizes集合上也是如此
如果将来您决定以不同的方式定义较小的纸张大小,则LINQ语句不必更改
优化
如果你只想要最小的,那么订购所有尺寸的纸张是相当浪费的。考虑使用最小纸张尺寸< /P>
FirstOrDefault?我只是复制了他的代码-我不想引入与解决他的问题无关的编辑。他的代码中没有?PaperName或FirstOrDefault。事实上,他的列表是按大小排序的。我想他已经想到了。等等,事实上这不完全是真的。我将添加一条注释。@croxy但他应该有一个FirstOrDefault以避免NullreferenceExceptionFirstOrDefault?我只是复制了他的代码-我不想引入与解决他的问题无关的编辑。他的代码中没有?.PaperName或FirstOrDefault。事实上,他的列表是按大小排序的。我想他已经想到了。等等,事实上这不完全是真的。我要加一个注释。@croxy,但他应该有一个第一个或第一个默认值,以避免出现空引用例外。这个问题是为了平等或更高,这严格要求更高的论文。因此,p=>p.W>=宽度将是一条可行之路。也可能最好采用FirstOrDefault而不是First。除此之外,这个答案可能就是OP想要的。问题是关于eq
或者更高,这需要更高的论文。因此,p=>p.W>=宽度将是一条可行之路。也可能最好采用FirstOrDefault而不是First。除此之外,这个答案可能是OP正在寻找的。记住在当前的解决方案中,你可能会考虑最近的纸张大小。由于这似乎是用于打印,因此使用OrderBy总未使用像素可能会比建议的OrderBy稍微复杂一些。这实际上可以减少废纸的数量,我认为这是保护树木目标的一部分!!NVM,只是注意到区域添加已经在另一个答案中提到了:在当前的解决方案中要考虑到你可能考虑最近的纸张大小。由于这似乎是用于打印,因此使用OrderBy总未使用像素可能会比建议的OrderBy稍微复杂一些。这实际上可以减少废纸的数量,我认为这是保护树木目标的一部分!!nvm,刚刚注意到另一个答案中已经提到了面积增加:-
var smallestFittingPapersizeName = availablePaperSizes
.Where(paperSize => paperSize.Width >= width && paperSize.Height >= height)
.OrderBy(paperSize, PaperSizeComparer.AreaComparer)
.Select(paperSize => paperSize.Name)
.FirstOrDefault();
// instead of OrderBy:
.Aggregate( (paperSizeX, paperSizeY) =>
((PaperSizeComparer.AreaComparer.Compare(paperSizeX, paperSizeY) <= 0) ??
// paperSizeX smaller or equal; X remains the smallest
paperSizeX :
// paperSizeX larger: Y is the new smalles:
paperSizeY)
public TSource MinOrDefault<TSource> (this IEnumerable<TSource> source,
IComparer<TSource) comparer)
{
// TODO: exception if source == null
if (comparer == null)
comparer = Comparer<TSource>.Default; // use default comparer
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{ // we have at least one source element:
var smallest = enumerator.Current;
// continue with the rest of the input sequence:
while (enumerator.MoveNext())
{
// there is still another item
if (comparer.CompareTo(smallest, enumerator.Current) > 0)
{
// found a smaller item:
smallest = enumerator.Current;
}
}
return smallest;
}
else
{ // input collection empty; return default
return default(TSource);
}
}
PaperSize smallestFittingPaperSize = availablePaperSizes
.Where(paperSize => paperSize.Width >= width && paperSize.Height >= height)
.Min(PaperSizeComparer.AreaCompaerer);