需要在Python中匹配文件中的字符串到行

时间:2012-11-21 17:48:23

标签: python file list format abbreviation

我第一次在这里问一些事情。我有一个名称的文本文件,每行1个名字,我正在读入列表,然后复制该列表两次,第一次删除\ n&n;以及第二次小写名单。然后我问用户一个搜索词,并将他们的输入转换为小写,然后搜索列表的小写版本,然后我得到匹配的索引,并使用它来显示该非小写版本将项目列回给用户(因此他们可以键入例如anivia并返回Anivia)。这工作正常,但我确定我的代码非常糟糕。我想要做的是为列表文件中的某些名称添加特定的缩写,并接受这些缩写作为输入,但仍然显示全名。例如,用户输入" mumu"并且它看到该列表有Amumu - mumu,参考Amumu。我怎么能接受这种缩减?还有其他一些案例,比如“财富小姐”的mf或者Kha&#Z; Z的kha。我想可能有第二个文件包含缩写列表,但这看起来很浪费,我确信这是一个更好的方法。到目前为止,这是我的错误代码:

f = open("champions.txt") #open the file
list = f.readlines() #load each line into the list
#print list
list2 = [item.rstrip('\n') for item in list] #remove trailing newlines in copy list
list3 = [item.lower() for item in list2] #make it all lowercase

print "-------\n", list2 #print the list with no newlines just to check

print "which champ" #ask user for input
value = raw_input().lower() #get the input and make it lowercase
if value in list3: #check list for value and then print back a message using that index but from the non-lowercase list
    pos = list3.index(value)
    print "list contains", list2[pos]
else: #if the input doesn't match an item print an error message
    print "error"

一旦它以我需要的方式工作,就把这一切都放在我的主文件中。基本上我想更改我的文本文件中的某些行以具有有效的备用缩写,并且能够接受这些中的行并仍然将完整名称显示回用户。例如,我的辅助文本文件中包含缩写的行之一有一行:

Kog'Maw - kogmaw, kog, km

我如何简化我所拥有的并添加该功能?我不确定从哪里开始,我对python和编程一般都很陌生。感谢您提供任何帮助,对不起这么长的帖子感到抱歉。

2 个答案:

答案 0 :(得分:2)

好的,这是一个修改后的答案,假设有一个文件包含this开头所示的名称和缩写。

它本质上是做一个大的查找表,它将文件中的任何缩写以及小写的名称本身映射到每行开头的名称。

lookup = {}
with open("champions.txt") as f:
    for line in f:
        line = line.rstrip().split('-', 1)
        if not line: continue # skip any blank lines

        name = line[0].strip()
        lookup[name.lower()] = name
        if len(line) == 2:  # any alternative names given?
            for item in line[1].split(','):
                lookup[item.strip()] = name

print 'lookup table:'
for alt_name, real_name in sorted(lookup.items()):
    print '{}: {}'.format(alt_name, real_name)
print

while True:
    print "which champ (Enter to quit): "  # ask user for input
    value = raw_input().lower()  # get the input and make it lowercase
    if not value: break

    real_name = lookup.get(value)
    if real_name:
        print 'found:', value, '-->', real_name
    else:
        print 'error: no match for', value

答案 1 :(得分:0)

首先,您应该使用有用的名称。因此,而不是list2将其称为lower_names等等。

其次,您可以通过一次in调用替换index运算符和index调用。如果您注意到,对some_list.index(item_which_does_not_exist)的调用将引发valueError,表示该项目不在列表中。最“pythonic”的方法是try获取索引except如果失败,那么你会做其他事情。

所以你可以用这个替换if部分:

try:
    pos = list3.index(value)
except ValueError:
    print 'error'
else:
    print 'everything is ok. there was no exception raised'
    print 'list contains', list2[pos]

在蟒蛇哲学中经常说,要求宽恕比获得许可更好。 :)

另一个重要的事情,这只是假设你想要将小写名称与其“真实”名称相匹配,你需要一个字典。字典将键映射到值,因此您在此处需要将每个小写名称(键)映射到实际名称(值)。它可以这样定义(我看你熟悉一个衬里):

name_map = {item.lower(): item for item in (line.strip() for line in f)}

因此,您可以直接遍历文件,而不是使用readlines。这是Python中的额外糖。

然后,您可以执行以下操作:value in name_mapreal_name = name_map[value]

至于额外的功能,我会选择第二个选项,即name - nickname1,nickname2。所以你需要做的是:读取每一行,用短划线-(或任何其他不会在名称中使用的字符)拆分,然后用逗号分隔第二部分,使每个名字单独使用。总结:

name_map = {}
nick_map = {}
for line in f:
    parts = line.strip().split('-')
    name = parts[0].strip()
    nicks = {n.strip(): name for n in parts[1].split(',')}
    name_map[name.lower()] = name
    nick_map.update(nicks)

# To check a name:
if value in name_map:
   # Exact match
elif value in nick_map:
   # Nickname match
else:
   # No Match

您可以使用try / except / else子句执行等效操作,但这会产生太多嵌套,不推荐使用。