排序列表多个键和最近的值
Sort list multiple key and upper nearest value
我想如何排序我的列表:
- isRegular = True
- 粗体 = 正确
- 斜体 = 正确
- 最近的权重上限值。在我的示例中,我想要最接近 400 的值。
我的列表包含这些 NamedTuple:
class Font(NamedTuple):
fontPath: str
fontName: str
isRegular: bool
bold: bool
italic: bool
weight: int
这是我现在的排序方式(不太好)
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, -abs(400 - font.weight)))
输入
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
]
我目前的输出(如果我多次尝试 运行 代码,它会给我不同的输出。我不知道为什么会这样。这是我可以获得的 2 个输出示例)
# Output 1
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800)
]
# Output 2
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
]
这是我想要的输出
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900)
]
list.sort()
默认为升序。你不需要做 -abs(400 - font.weight)
。去掉前面的负号即可:
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, abs(400 - font.weight)))
注意:对于300和500的情况(与400的距离相等),300会排在第一位,因为它是按升序排列的。如果你想要反过来,在元组中包含 -font.weight
像这样:
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, abs(400 - font.weight), -font.weight))
定义一个old-style比较函数,functools.cmp_to_key
会变成一个合适的键函数。
from functools import cmp_to_key
def compare(f1, f2):
if f1.isRegular and f2.isRegular:
if f1.bold and f2.bold:
if f1.italic and f2.italic:
d1 = abs(f1.weight - 400)
d2 = abs(f2.weight - 400)
return f1 if d1 <= d2 else f2
else:
return f1 if f1.italic else f2
else:
return f1 if f1.bold else f2
else:
return f1 if f2.bold else f2
fontMatch.sort(key=cmp_to_key(compare))
compare
至少可以说有点冗长。您可能想根据 Python 2 的旧 cmp
函数来定义它,在这里简单地重新定义。
def cmp(x, y):
return -1 if x < y else 0 if x == y else 1
def compare(f1, f2, w=400):
# Since False < True, we swap the order of the arguments
# for the boolean fields.
return (cmp(f2.isRegular, f1.isRegular)
or cmp(f2.bold, f1.bold)
or cmp(f2.italic, f1.italic)
or cmp(abs(f1.weight - w), abs(f2.weight - w)))
目标权重参数化后,可以使用
fontMatch.sort(key=cmp_to_key(compare))
fontMatch.sort(key=cmp_to_key(lambda x, y: compare(x,y,700))
# etc
你也可以考虑一个只需要权重的工厂函数:
def make_compare(w=400):
def compare(x, y):
return (cmp(f2.isRegular, f1.isRegular)
or cmp(f2.bold, f1.bold)
or cmp(f2.italic, f1.italic)
or cmp(abs(f1.weight - w), abs(f2.weight - w)))
fontMatch.sort(key=cmp_to_key(make_compare()))
fontMatch.sort(key=cmp_to_key(make_compare(700)))
# etc
使用比较函数可以让您更精确地 per-field 排序,而不必求助于否定技巧(无论如何只适用于数字字段)。
我想如何排序我的列表:
- isRegular = True
- 粗体 = 正确
- 斜体 = 正确
- 最近的权重上限值。在我的示例中,我想要最接近 400 的值。
我的列表包含这些 NamedTuple:
class Font(NamedTuple):
fontPath: str
fontName: str
isRegular: bool
bold: bool
italic: bool
weight: int
这是我现在的排序方式(不太好)
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, -abs(400 - font.weight)))
输入
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
]
我目前的输出(如果我多次尝试 运行 代码,它会给我不同的输出。我不知道为什么会这样。这是我可以获得的 2 个输出示例)
# Output 1
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800)
]
# Output 2
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
]
这是我想要的输出
[
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Regular_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=True, bold=False, italic=False, weight=400),
Font(fontPath='C:\Windows\Fonts\Deleted\MADE TOMMY BOLD_PERSONAL USE.OTF', fontName='MADE TOMMY', isRegular=False, bold=True, italic=False, weight=700),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Medium_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=500),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Light_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=300),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Thin_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=250),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY ExtraBold_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=800),
Font(fontPath='C:\Windows\Fonts\MADE TOMMY Black_PERSONAL USE.otf', fontName='MADE TOMMY', isRegular=False, bold=False, italic=False, weight=900)
]
list.sort()
默认为升序。你不需要做 -abs(400 - font.weight)
。去掉前面的负号即可:
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, abs(400 - font.weight)))
注意:对于300和500的情况(与400的距离相等),300会排在第一位,因为它是按升序排列的。如果你想要反过来,在元组中包含 -font.weight
像这样:
fontMatch.sort(key=lambda font: (-font.isRegular, -font.bold, -font.italic, abs(400 - font.weight), -font.weight))
定义一个old-style比较函数,functools.cmp_to_key
会变成一个合适的键函数。
from functools import cmp_to_key
def compare(f1, f2):
if f1.isRegular and f2.isRegular:
if f1.bold and f2.bold:
if f1.italic and f2.italic:
d1 = abs(f1.weight - 400)
d2 = abs(f2.weight - 400)
return f1 if d1 <= d2 else f2
else:
return f1 if f1.italic else f2
else:
return f1 if f1.bold else f2
else:
return f1 if f2.bold else f2
fontMatch.sort(key=cmp_to_key(compare))
compare
至少可以说有点冗长。您可能想根据 Python 2 的旧 cmp
函数来定义它,在这里简单地重新定义。
def cmp(x, y):
return -1 if x < y else 0 if x == y else 1
def compare(f1, f2, w=400):
# Since False < True, we swap the order of the arguments
# for the boolean fields.
return (cmp(f2.isRegular, f1.isRegular)
or cmp(f2.bold, f1.bold)
or cmp(f2.italic, f1.italic)
or cmp(abs(f1.weight - w), abs(f2.weight - w)))
目标权重参数化后,可以使用
fontMatch.sort(key=cmp_to_key(compare))
fontMatch.sort(key=cmp_to_key(lambda x, y: compare(x,y,700))
# etc
你也可以考虑一个只需要权重的工厂函数:
def make_compare(w=400):
def compare(x, y):
return (cmp(f2.isRegular, f1.isRegular)
or cmp(f2.bold, f1.bold)
or cmp(f2.italic, f1.italic)
or cmp(abs(f1.weight - w), abs(f2.weight - w)))
fontMatch.sort(key=cmp_to_key(make_compare()))
fontMatch.sort(key=cmp_to_key(make_compare(700)))
# etc
使用比较函数可以让您更精确地 per-field 排序,而不必求助于否定技巧(无论如何只适用于数字字段)。