【问题标题】:Select random lines from a text file without repeats in Python从文本文件中选择随机行而不在 Python 中重复
【发布时间】:2021-03-16 21:35:54
【问题描述】:

我有一个程序可以打印歌曲的首字母和他们的艺术家,你必须猜出这首歌。

我希望随机选择歌曲,但只显示一次,并且我希望在列表中的所有歌曲都显示后结束游戏。

这是我的文本文件“songs.txt”的示例:

Billie Eilish - 派对结束时
Ariana Grande - 男朋友
TMC - 无磨砂
命运之子 - 说出我的名字
阿黛尔 - 你好
凯蒂佩里 - 加州女孩
防弹少年团 - 主页

这是我的输出:

The first letter of the song is: H and the artist is: BTS

这是我的代码:

   import random
   def random_line(songs):
       lines = open(songs).read().splitlines()
       return random.choice(lines)
   random =(random_line('songs.txt'))
   artist = (random.split(' - ')[0])
   song = (random.split(' - ',1)[1])
   song_letter = song[0]
   print ("The first letter of the song is: " + song_letter + " and the artist is: " + artist) 

【问题讨论】:

  • 为什么不只是 shuffle 列表并循环浏览改组的版本?
  • 这个我不知道,我去研究一下,谢谢!

标签: python loops file random repeat


【解决方案1】:

我假设您将在某种 while 或 for 循环中运行它,并且可能需要根据实际存储的输入来评估用户输入。因此,您可能希望在函数中包含回归艺术家 song_letter。你没有收到第一个字母,因为你没有足够远地索引歌曲

import random

"""I've used a list of the songs you provided but you may wish to import these from a txt file and then convert to a list"""

songs = ['Billie Eilish - When The Party Is Over',
         'Ariana Grande - boyfriend',
        'TMC - No Scrubs',
        "Destiny's Child - Say My Name",
        "Adele - Hello",
        "Katy Perry - California Girls",
        "BTS - Home"]



def artist_song(song):
    artist = song.split(' - ')[0]
    song_letter = song.split(' - ')[1][0]
    print ("The first letter of the song is: " + song_letter + " and the artist is: " + artist)

    """You may chose to use return (artist,song_letter) insteas so you can use them for comparision"""

song = random.choice(songs) 
artist, song_letter = artist_song(song)
songs.remove(song)

您可能希望多次执行此操作,直到没有单独的任何歌曲,您可以按以下方式执行此操作:


while songs:
    song = random.choice(songs) 
    artist, song_letter = artist_song(song)
    x = input('User input here: ').lower()
    if x == song.split(' - ')[1].lower():
        """What to do if their input matches"""
        pass
    else:
        """What to do if the song is wrong"""
        pass
    songs.remove(song)

对于输入,请考虑其他因素,例如输入验证,因此请确保用户输入只有字母,没有数字/空格等。您可以包含一个计数器来跟踪分数。

【讨论】:

    【解决方案2】:

    random.choice(lines) 存储在一个变量中,然后将其从行列表中删除。

      def random_line(songs):
            lines = open(songs).read().splitlines()        
            random_line =  random.choice(lines)
            lines.remove(random_line)        
            return random_line
    

    【讨论】:

      【解决方案3】:

      这里有一个生成器形式的解决方案,它基于洗牌并使用yield 实现。洗牌需要 O(n) 时间来处理 n 个项目的列表,该时间在迭代中摊销以产生每首歌曲的恒定时间。与从列表中删除解决方案相比,它的一个优点是生成器可以多次运行,如下面的代码所示。它将遍历整个序列,但如果您继续请求更多歌曲,则会产生不同的顺序。

      import random
      
      song_list = [
          "Billie Eilish - When The Party Is Over",
          "Ariana Grande - boyfriend",
          "TMC - No Scrubs",
          "Destiny's Child - Say My Name",
          "Adele - Hello",
          "Katy Perry - California Girls",
          "BTS - Home"
      ]
      
      def song_info():
          random.shuffle(song_list)
          for i in range(len(song_list)):
              yield song_list[i].split(' - ')
      
      def playlist():
          for (artist, title) in song_info():
              print ("The first letter of the song is: " + title[0] + " and the artist is: " + artist)
      
      playlist()
      print("That was so fun, let's do it again!")
      playlist()
      

      如果您预计您的歌曲“数据库”会增长,显然您可以通过从文件中读取而不是将其硬连线到代码中来填充 song_list

      将数据存储为艺术家和标题的列表/元组而不是作为要拆分的字符串也可能更有意义。这会将song_listsong_info() 生成器更改为:

      song_list = [
          ("Billie Eilish", "When The Party Is Over"),
          ("Ariana Grande", "boyfriend"),
          ("TMC", "No Scrubs"),
          ("Destiny's Child", "Say My Name"),
          ("Adele", "Hello"),
          ("Katy Perry", "California Girls"),
          ("BTS", "Home")
      ]
      
      def song_info():
          random.shuffle(song_list)
          for i in range(len(song_list)):
              yield song_list[i]
      

      在我看来这更干净。

      【讨论】:

        猜你喜欢
        • 2020-02-19
        • 1970-01-01
        • 2020-01-16
        • 1970-01-01
        • 1970-01-01
        • 2012-01-10
        • 1970-01-01
        • 1970-01-01
        • 2012-03-03
        相关资源
        最近更新 更多