【问题标题】:Looping through a txt file循环遍历一个txt文件
【发布时间】:2021-12-09 09:04:45
【问题描述】:

我有一个 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:

我怎样才能得到比艺术家姓名高两行的歌曲名称?一个艺术家也有可能出现多次,演唱不同的歌曲。

【问题讨论】:

  • 如果一个艺术家有多首歌曲怎么办?
  • 为什么需要header?您的示例文件中没有任何标题

标签: python file txt


【解决方案1】:

到目前为止,所有答案都是有效的,但它们确实依赖于格式始终为 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,您可以研究模式匹配以进一步简化代码。

【讨论】:

    【解决方案2】:

    从第二个元素开始(因为那是第一个艺术家所在的位置)并每隔 4 个元素扫描艺术家。如果linelisti-th 元素与artist 匹配,则打印歌曲(位于i-2)。

    for i in range(2, 100, 4):
        if linelist[i] == artist:
            print(linelist[i-2])
    

    【讨论】:

    • afile.readlines() 已经给你一个列表
    • @PranavHosangadi 好点。
    【解决方案3】:

    首先,将您的文件读入一个列表。我假设您的文件格式是固定的:它包含

    • 指定歌曲名称的一行
    • 指定流派的行
    • 指定艺术家的行
    • 空行
    • 重复

    请注意,由于似乎没有标头,因此您不需要初始的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 列表分割为每四行,从第一行开始,并将其保存为名为@9​​87654326@ 的列表
    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   
    

    如果您是为一群艺术家这样做,我建议您先将数据读入字典(or a 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)
    

    您可以不必将整个文件读入一个列表,然后通过以四行为一组逐行读取文件来将其处理成字典,但我将把它留给您作为练习。

    【讨论】:

      【解决方案4】:

      假设每个艺术家只有一首歌(或者您正在搜索第一场比赛),您可以这样解决:

      
      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"
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-05
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 2019-07-21
        • 2019-01-03
        • 2018-01-15
        相关资源
        最近更新 更多