以下可以通过一步一步,有些笨拙的方式来完成,但我想知道是否有优雅的方法来做到这一点.
有一个页面:http://www.mariowiki.com/Mario_Kart_Wii,其中有2个表...有
Mario - 6 2 2 3 - -
Luigi 2 6 - - - - -
Diddy Kong - - 3 - 3 - 5
[...]
Run Code Online (Sandbox Code Playgroud)
"Mario"等名称是Mario Kart Wii角色名称.这些数字是奖励积分:
Speed Weight Acceleration Handling Drift Off-Road Mini-Turbo
Run Code Online (Sandbox Code Playgroud)
然后是表2
Standard Bike S 39 21 51 51 54 43 48
Bullet Bike 53 24 32 35 67 29 67
Bubble Bike / Jet Bubble 48 27 40 40 45 35 37
[...]
Run Code Online (Sandbox Code Playgroud)
这些也是Bike或Kart的特征.
我想知道什么是找到速度,重量,加速度等所有最大组合的最优雅的解决方案,并且最低限度,通过直接使用该页面上的HTML或复制并将数字粘贴到文本文件中.
实际上,在那个角色表中,Mario to Bower Jr都是中等角色,Baby Mario to Dry Bones是小角色,其余都是大角色,除了小,中,或大Mii就像名字所说的那样.小角色只能骑小型自行车或小型卡丁车,大中型等等.
更新:在打印结果时过滤掉卡丁车类型或自行车会很不错,因为有些人只玩自行车,而且仅适用于自行车的"进入"或"外出"漂移类型,因为有些人只玩使用"in"漂移型.同样不错的是打印出具有相同最大值或最小值的结果(不同卡丁车或自行车上的不同字符加起来相同的值).Hugh打印出最高值和最低值的答案也很好,因为有些值非常接近,例如73或72.
你的问题分为两部分.解析HTML并进行分析.解析HTML是一项繁琐的工作,我怀疑你可以做很多事情来使它变得优雅.分析并不难,但有一些方法可以在Python中做到这一点,我认为可能会被认为是优雅的.我将讨论以优雅和简洁的方式表达蛮力分析的方法.我不打算比蛮力更快地讨论如何做到这一点,因为数据集非常小.
import collections
Stats = collections.namedtuple("Stats", "speed weight acceleration handling drift offroad turbo")
Run Code Online (Sandbox Code Playgroud)
首先,我们创建一个名为"Stats"的命名元组.这是我们用来表示驾驶员或车辆的统计数据的对象.命名元组很好,因为:
driver.weight__str__格式:"Stats(speed=73, weight=56, acceleration=21, handling=17, drift=27, offroad=19, turbo=16)"让我们定义一个函数来添加两组统计信息:
def add_stats(xs, ys):
return Stats(*[(x+y) for (x,y) in zip(xs,ys)])
Run Code Online (Sandbox Code Playgroud)
Zip采用两个序列并从每个序列返回一系列项目.例如zip([1,2,3],['a','b','c'])== [(1,'a'),(2,'b'),(3,'c') )]).然后我们使用list comprehension([blah for blah in blah])将每个对中的统计数据加在一起.最后,我们将其提供给Stats构造函数.*表示我们希望将序列中的每个项目用作函数的参数.
class ThingWithStats(object):
def __init__(self, name, stats):
self.name = name
self.stats = Stats(*stats)
def __str__(self):
return self.name + " (" + str(self.stats) + ")"
class Driver(ThingWithStats):
pass
class Vehicle(ThingWithStats):
pass
class Combination(ThingWithStats):
def __init__(self, driver, vehicle):
self.name = driver.name + " riding " + vehicle.name
self.stats = add_stats(driver.stats, vehicle.stats)
Run Code Online (Sandbox Code Playgroud)
现在我们已经定义了类来表示驱动程序,车辆和两者的组合.请注意,Driver和Vehicle的构造函数(继承自ThingWithStats)可以采用任何适当长度的序列作为其stats参数.他们使用a *将序列转换为Stats对象.我们很快就会明白为什么这很方便.
def make_combinations(drivers, vehicles):
return [
Combination(driver, vehicle)
for driver in drivers
for vehicle in vehicles]
Run Code Online (Sandbox Code Playgroud)
此功能使用列表推导来查找某些驱动程序列表和某些车辆列表的所有组合.请注意,通过在单个理解中使用多个"for",我们可以获得所有组合.这有时也被称为笛卡尔积.
现在这里有一点点数据 - 数据.我复制并粘贴了这些并使用了一些vim魔法将它们按到正确的格式.对不起,我没有更聪明的事情.请注意,对于stats参数,我们传递一个常规元组.如上所述,构造函数转换为Stats对象.这节省了我们一点点的混乱.
medium_drivers = [
Driver("Mario", (0, 6, 2, 2, 3, 0, 0)),
Driver("Luigi", (2, 6, 0, 0, 0, 0, 0)),
Driver("Peach", (2, 0, 5, 0, 6, 0, 0)),
Driver("Daisy", (4, 0, 0, 2, 0, 0, 3)),
Driver("Yoshi", (0, 3, 0, 0, 3, 5, 0)),
Driver("Birdo", (0, 3, 0, 0, 0, 3, 5)),
Driver("Diddy Kong", (0, 0, 3, 0, 3, 0, 5)),
Driver("Bowser Jr.", (0, 0, 0, 0, 0, 3, 3)),
Driver("Medium Mii", (3, 3, 0, 0, 0, 3, 3)),
]
small_drivers = [
Driver("Baby Mario", (0, 8, 0, 6, 0, 0, 0)),
Driver("Baby Luigi", (5, 8, 0, 0, 0, 0, 0)),
Driver("Baby Peach", (3, 6, 3, 3, 0, 0, 0)),
Driver("Baby Daisy", (5, 6, 0, 0, 0, 0, 3)),
Driver("Toad", (0, 0, 6, 0, 6, 0, 0)),
Driver("Toadette", (3, 0, 0, 0, 0, 6, 0)),
Driver("Koopa Troopa", (0, 0, 0, 3, 0, 0, 6)),
Driver("Dry Bones", (0, 0, 3, 0, 3, 0, 6)),
Driver("Small Mii", (3, 3, 0, 0, 3, 0, 3)),
]
large_drivers = [
Driver("Wario", (0, 3, 0, 0, 0, 3, 6)),
Driver("Waluigi", (0, 0, 6, 0, 5, 3, 0)),
Driver("Donkey Kong", (0, 3, 2, 2, 0, 0, 3)),
Driver("Bowser", (2, 5, 0, 0, 3, 0, 0)),
Driver("King Boo", (0, 0, 0, 5, 0, 3, 0)),
Driver("Rosalina", (3, 0, 0, 3, 0, 0, 3)),
Driver("Funky Kong", (4, 0, 0, 0, 0, 3, 0)),
Driver("Dry Bowser", (0, 0, 0, 0, 0, 6, 6)),
Driver("Large Mii", (3, 0, 3, 3, 3, 0, 3)),
]
small_vehicles = [
Vehicle("Standard Kart S", (41, 29, 48, 48, 51, 40, 45)),
Vehicle("Baby Booster / Booster Seat", (27, 27, 56, 64, 37, 54, 59)),
Vehicle("Concerto / Mini Beast", (55, 32, 29, 32, 64, 27, 64)),
Vehicle("Cheep Charger", (34, 24, 64, 56, 59, 45, 54)),
Vehicle("Rally Romper / Tiny Titan", (46, 35, 43, 43, 29, 64, 40)),
Vehicle("Blue Falcon", (60, 29, 35, 29, 43, 24, 29)),
Vehicle("Standard Bike S", (39, 21, 51, 51, 54, 43, 48)),
Vehicle("Bullet Bike", (53, 24, 32, 35, 67, 29, 67)),
Vehicle("Nano Bike / Bit Bike", (25, 18, 59, 67, 40, 56, 62)),
Vehicle("Quacker", (32, 17, 67, 60, 62, 48, 57)),
Vehicle("Magikruiser", (43, 24, 45, 45, 32, 67, 43)),
Vehicle("Bubble Bike / Jet Bubble", (48, 27, 40, 40, 45, 35, 37)),
]
medium_vehicles = [
Vehicle("Standard Kart M", (46, 45, 40, 43, 45, 35, 40)),
Vehicle("Nostalgia 1 / Classic Dragster", (37, 43, 59, 54, 54, 40, 51)),
Vehicle("Wild Wing", (57, 51, 21, 29, 59, 24, 59)),
Vehicle("Turbo Blooper / Super Blooper", (50, 40, 35, 37, 21, 54, 35)),
Vehicle("Royal Racer / Daytripper", (34, 45, 51, 59, 32, 48, 54)),
Vehicle("B Dasher Mk. 2 / Sprinter", (64, 48, 27, 24, 37, 21, 24)),
Vehicle("Standard Bike M", (43, 37, 43, 45, 48, 37, 43)),
Vehicle("Mach Bike", (55, 37, 24, 32, 62, 27, 62)),
Vehicle("Bon Bon / Sugarscoot", (32, 32, 54, 62, 35, 51, 56)),
Vehicle("Rapide / Zip Zip", (41, 35, 45, 51, 29, 62, 45)),
Vehicle("Nitrocycle / Sneakster", (62, 40, 29, 27, 40, 24, 27)),
Vehicle("Dolphin Dasher", (48, 43, 37, 40, 24, 56, 37)),
]
large_vehicles = [
Vehicle("Standard Kart L", (48, 59, 37, 40, 40, 35, 35)),
Vehicle("Offroader", (39, 64, 48, 54, 18, 43, 45)),
Vehicle("Flame Flyer", (62, 59, 16, 21, 48, 18, 48)),
Vehicle("Piranha Prowler", (55, 67, 29, 35, 35, 29, 27)),
Vehicle("Aero Glider / Jetsetter", (69, 56, 21, 17, 27, 16, 16)),
Vehicle("Dragonetti / Honeycoupe", (53, 62, 27, 29, 56, 24, 56)),
Vehicle("Standard Bike L", (46, 54, 40, 43, 43, 37, 37)),
Vehicle("Bowser Bike / Flame Runner", (60, 54, 18, 24, 51, 21, 51)),
Vehicle("Wario Bike", (37, 59, 51, 56, 21, 45, 48)),
Vehicle("Twinkle Star / Shooting Star", (50, 48, 29, 32, 59, 27, 59)),
Vehicle("Torpedo / Spear", (67, 56, 24, 18, 29, 18, 18)),
Vehicle("Phantom", (43, 51, 43, 48, 17, 56, 40)),
]
Run Code Online (Sandbox Code Playgroud)
有了这个,我们列出了所有组合:
small_combinations = make_combinations(small_drivers, small_vehicles)
medium_combinations = make_combinations(medium_drivers, medium_vehicles)
large_combinations = make_combinations(large_drivers, large_vehicles)
all_combinations = small_combinations + medium_combinations + large_combinations
Run Code Online (Sandbox Code Playgroud)
最后,我们对所有组合列表进行了一些基本分析:
print "Max speed:", max(all_combinations, key=lambda c:c.stats.speed)
print "Max weight:", max(all_combinations, key=lambda c:c.stats.weight)
print "Max acceleration:", max(all_combinations, key=lambda c:c.stats.acceleration)
print "Max handling:", max(all_combinations, key=lambda c:c.stats.handling)
print "Max drift:", max(all_combinations, key=lambda c:c.stats.drift)
print "Max offroad:", max(all_combinations, key=lambda c:c.stats.offroad)
print "Max turbo:", max(all_combinations, key=lambda c:c.stats.turbo)
print
print "Min speed:", min(all_combinations, key=lambda c:c.stats.speed)
print "Min weight:", min(all_combinations, key=lambda c:c.stats.weight)
print "Min acceleration:", min(all_combinations, key=lambda c:c.stats.acceleration)
print "Min handling:", min(all_combinations, key=lambda c:c.stats.handling)
print "Min drift:", min(all_combinations, key=lambda c:c.stats.drift)
print "Min offroad:", min(all_combinations, key=lambda c:c.stats.offroad)
print "Min turbo:", min(all_combinations, key=lambda c:c.stats.turbo)
Run Code Online (Sandbox Code Playgroud)
该min和max功能提供了一个key出于这样的目的的说法.它需要一个函数从列表中获取一个项目并返回您想要排序的值.结果如下:
Max speed: Funky Kong riding Aero Glider / Jetsetter (Stats(speed=73, weight=56, acceleration=21, handling=17, drift=27, offroad=19, turbo=16))
Max weight: Bowser riding Piranha Prowler (Stats(speed=57, weight=72, acceleration=29, handling=35, drift=38, offroad=29, turbo=27))
Max acceleration: Toad riding Quacker (Stats(speed=32, weight=17, acceleration=73, handling=60, drift=68, offroad=48, turbo=57))
Max handling: Baby Mario riding Nano Bike / Bit Bike (Stats(speed=25, weight=26, acceleration=59, handling=73, drift=40, offroad=56, turbo=62))
Max drift: Toad riding Bullet Bike (Stats(speed=53, weight=24, acceleration=38, handling=35, drift=73, offroad=29, turbo=67))
Max offroad: Toadette riding Magikruiser (Stats(speed=46, weight=24, acceleration=45, handling=45, drift=32, offroad=73, turbo=43))
Max turbo: Koopa Troopa riding Bullet Bike (Stats(speed=53, weight=24, acceleration=32, handling=38, drift=67, offroad=29, turbo=73))
Min speed: Baby Mario riding Nano Bike / Bit Bike (Stats(speed=25, weight=26, acceleration=59, handling=73, drift=40, offroad=56, turbo=62))
Min weight: Toad riding Quacker (Stats(speed=32, weight=17, acceleration=73, handling=60, drift=68, offroad=48, turbo=57))
Min acceleration: Wario riding Flame Flyer (Stats(speed=62, weight=62, acceleration=16, handling=21, drift=48, offroad=21, turbo=54))
Min handling: Wario riding Aero Glider / Jetsetter (Stats(speed=69, weight=59, acceleration=21, handling=17, drift=27, offroad=19, turbo=22))
Min drift: Wario riding Phantom (Stats(speed=43, weight=54, acceleration=43, handling=48, drift=17, offroad=59, turbo=46))
Min offroad: Donkey Kong riding Aero Glider / Jetsetter (Stats(speed=69, weight=59, acceleration=23, handling=19, drift=27, offroad=16, turbo=19))
Min turbo: Waluigi riding Aero Glider / Jetsetter (Stats(speed=69, weight=56, acceleration=27, handling=17, drift=32, offroad=19, turbo=16))
Run Code Online (Sandbox Code Playgroud)
更多想法
如果你不想要这个应用到更大的数据集,你可以找到的最小和最大为每个统计司机和车辆,然后对每个统计与最大车辆和最小驱动程序与分钟车相结合的最大驱动.那将是O(M log M + N log N)而不是O(M*N log M*N).但在我认为这是一个问题之前,你真的需要接触成千上万的司机和车辆.
如果要将其应用于甚至不适合内存的海量数据集,则可以使用生成器表达式而不是列表推导.您需要将其与可以一次读取并生成一个驱动程序/车辆的解析器相结合.
您可以通过添加约束来执行更具体的搜索.例如,要找到turbo> = 50且处理> = 40的最快组合:
max((combination
for combination in all_combinations
if combination.stats.turbo >= 50
and combination.stats.handling >= 40),
key=lambda c:c.stats.speed)
Run Code Online (Sandbox Code Playgroud)
如果你想让所有那些并列为顶级的人,你可以这样做:
def all_max(sequence, key):
top_value = key(max(sequence, key=key))
return [item for item in sequence if key(item) == top_value]
Run Code Online (Sandbox Code Playgroud)
打电话就像你打电话一样max.它返回所有那些项目的列表,这些项目与任何键指定的最大值相关联.