我有一个看起来像的文本文件:
Josh123: Level 2
Marcus N: Level 4
Callie [L16]: Level 1
Ashley 4: Level 3
我想要的是它会按照各自的等级对它们进行排序并打印出来,就像这样:
Marcus N: Level 4
Ashley 4: Level 3
Josh123: Level 2
Callie [L16]: Level 1
有办法做到这一点吗?谢谢!
答案 0 :(得分:0)
有很多方法。这是一个简单的:
with open("myFile") as lines:
print(''.join(reversed(sorted(lines, key = lambda line:int(line.split()[-1])))))
稍微强一些的方式:
import re
def getLevel(line):
match = re.search('Level ([0-9]+)', line)
if match:
return int(match.groups()[0])
return 0
with open("myFile") as lines:
print(''.join(reversed(sorted(lines, key = getLevel))))
这将在末尾放置与“Level N”不匹配的行。将return 0
替换为return 9999
或类似内容,将其置于开头。
另请参阅Thomas Howard's answer below以获得更好的选择。
答案 1 :(得分:0)
你可以试试这个:
import re
with open('filename.txt') as f:
data = [i.strip('\n') for i in f]
final_data = '\n'.join(map(lambda x:x[0], sorted(zip(data, [int(re.findall('(?<=Level\s)\d+', i)[0]) for i in data]), key=lambda x:x[-1], reverse=True)))
输出:
Marcus N: Level 4
Ashley 4: Level 3
Josh123: Level 2
Callie [L16]: Level 1
答案 2 :(得分:0)
你可以去
import re
string = """
Josh123: Level 2
Marcus N: Level 4
Callie [L16]: Level 1
Ashley 4: Level 3
"""
rx = re.compile(r'.+Level (\d+)')
# create the list of tuples and sort em
sorted_students = sorted([(match.group(0), int(match.group(1)))
for match in rx.finditer(string)],
key = lambda x: x[1], reverse = True)
# join the first item of every tuple with \n
student = "\n".join(student[0] for student in sorted_students)
print(student)
哪个收益
Marcus N: Level 4
Ashley 4: Level 3
Josh123: Level 2
Callie [L16]: Level 1
<小时/> 这里的想法是与
Level [some digits here]
的每一行匹配,然后转换数字并按此排序。最后,再次将结果与\n
联系起来。
答案 3 :(得分:0)
另一种更强大的方法是实际构建用户对象,将它们存储在列表中,然后对其进行排序。它是可扩展的,如果你添加其他字段,你可以轻松地构建namedtuples:
""" Sort players by level
Read a text file, each line represents a user.
Sort these users by level in reversed order.
"""
import re
from collections import namedtuple
User = namedtuple('User', ['level', 'info']) # Named tuple stores user information.
LEVEL_PATTERN = re.compile(r'Level (?P<level>\d+)$') # This finds the users level, compiled only once.
users = [] # A place to hold the users
# Read players in
with open('players.txt') as players:
for player in players:
level = re.search(LEVEL_PATTERN, player).group('level')
users.append(User(level, (player.strip())))
# Sort, and print
for player in sorted(users, key=lambda player: int(player.level), reverse=True): # timeit 2.88, n=1000
print(player.info)
最佳
编辑使用点符号和数字排序而不是词典。
另请注意,可以移动此代码段的int()部分。例如,可以在首次保存级别时放置它,而不是在lambda表达式中放置:
for player in players:
level = int(re.search(LEVEL_PATTERN, player).group('level'))
users.append(User(level, (player.strip())))
或者,当创建nampedtuple
时:
level = re.search(LEVEL_PATTERN, player).group('level')
users.append(User(int(level), (player.strip()))) # tiemit 2.06, n=1000
从理论上讲,实际上,上述方法更快。根据我的有限样本,根据timeit,每个循环的速度快〜0.8。
这是有道理的,因为在比较期间进行转换可以比在摄入时进行更多转换。在分拣过程中每次比较需要更多时间。
此外,由于没有排序算法达到O(n),因此摄入转换是更好的方法。
答案 4 :(得分:0)
假设:
>>> print(txt)
Josh123: Level 2
Marcus N: Level 4
Callie [L16]: Level 1
Ashley 4: Level 3
你可以这样做:
>>> sorted(txt.splitlines(), key=lambda line: -int(line.split()[-1]))
['Marcus N: Level 4', 'Ashley 4: Level 3', 'Josh123: Level 2', 'Callie [L16]: Level 1']
答案 5 :(得分:0)
map_data={}
with open('file.txt','r') as f:
for line in f:
map_data[line.split(':')[1].strip().split()[1]]=line.strip()
print(list(map(lambda x:map_data[x],sorted(map_data,reverse=True))))
输出:
['Marcus N: Level 4', 'Ashley 4: Level 3', 'Josh123: Level 2', 'Callie [L16]: Level 1']