我有一个txt文件,里面有艺术家、歌曲和流派的列表,格式如下:
song 1
genre 1
artist 1
song 2
genre 2
artist 2
etc.
我得到了一个艺术家的名字,如果艺术家在文件中,我必须返回他们的歌曲名称。我写的代码是:
afile = open('music.txt')
header = afile.readline()
artists = afile.readlines()
afile.close()
for art in artists:
if art == artist:
我怎样才能得到歌曲的名字,它在歌手的名字上面两行?也有可能一个艺术家带着不同的歌曲出现几次。
首先,将文件读入列表。我假设你的文件格式是固定的:它包含
- 指定歌曲名称的行
- 指定类型 的行
- 指定artist 的行
- 空白行
注意,由于似乎没有标题,您不需要初始的header = afile.readline()
假设你将文件中的所有行读入一个名为lines
lines = [line.strip() for line in afile]
# You could also do
# lines = afile.readlines()
# but that would leave behind trailing line breaks at the end of each line
现在,你知道
- 从第一行开始,每隔四行为歌曲名。因此,将
lines
列表分割为每四行,从第一行开始,并将其保存为名为songs
的列表
songs = lines[0::4]
- 对其他信息做同样的事情:
genres = lines[1::4]
artists = lines[2::4]
现在,我们可以对这些列表进行zip()
,以同时遍历它们,并打印与我们正在寻找的艺术家匹配的歌曲:
look_for_artist = "artist 2"
print(f"Songs by {look_for_artist}:")
for artist, genre, song in zip(artists, genres, songs):
if artist == look_for_artist:
print(song, genre)
# if you know that every artist has only one song, you can break the loop here since you found it already
# break
如果你是为一群艺术家做这件事,我建议你先把数据读入字典(或collections.defaultdict
)。然后,你可以查找给定艺术家的字典值,这将比遍历列表快得多。
考虑到一个艺术家可以有多首歌的情况,我们将使用一个字典,其中键是艺术家的名字,值是包含他们所有歌曲的列表。
import collections
lookup_dict = collections.defaultdict(list)
for artist, genre, song in zip(artists, genres, songs):
lookup_dict[artist].append((genre, song))
然后,你所需要做的就是:
for genre, song in lookup_dict[look_for_artist]:
print(song, genre)
您可以不需要将整个文件读入列表,然后将其处理为字典,方法是一行一行地以四行为一组读入文件,但我将把它留给您作为练习。
假设每个艺人只有一首歌曲(或者您正在搜索第一首匹配的歌曲),您可以这样解决:
def check_artist(chosen_artist):
afile = open('music.txt')
while afile:
song = afile.readline()
afile.readline() # Ignore the second line
artist = afile.readline()
if atrist == chosen_artist:
return song.split("n")
afile.readline() # Ignore the empty line
afile.close()
return "The artists do not have a song"
从第二个元素开始(因为这是第一个艺术家所在的位置),然后每隔第四个元素扫描一次艺术家。如果linelist
的i-th
元素与artist
匹配,则打印歌曲(在i-2
处)。
for i in range(2, 100, 4):
if linelist[i] == artist:
print(linelist[i-2])
到目前为止所有的答案都是有效的,但它们确实依赖于格式总是4行的事实。如果有丢失的数据或有更多的数据,下面的代码也可以工作:
music = []
with open("music.txt") as f:
for line in f:
line = line.split()
# continue if line is empty
if not line:
continue
key = line.pop(0)
value = ' '.join(line)
# check for keys
if key=='song':
music.append({key: value})
if key=='genre':
music[-1].update({key: value})
if key=='artist':
music[-1].update({key: value})
这也是可扩展的,如果你的格式以后包含另一个键,如'album'.
如果你正在使用python3.10,你可以研究模式匹配来进一步简化代码。