在Python中,从文本文件中选择不重复的随机行

在Python中,从文本文件中选择不重复的随机行,python,loops,file,random,repeat,Python,Loops,File,Random,Repeat,我有一个程序,打印歌曲的第一个字母和他们的艺术家,你必须猜这首歌 我希望歌曲被随机选择,但只显示一次,我希望游戏结束后,列表中的所有歌曲都已显示 下面是我的文本文件“songs.txt”的一个示例: Billie Eilish-派对结束时 阿里安娜·格兰德-男朋友 TMC-无Scrubs 命运之子-说出我的名字 阿黛勒-你好 凯蒂·佩里-加利福尼亚女孩 BTS-家庭 以下是我的输出: 歌曲的第一个字母是:H,歌手是:BTS 这是我的密码: import random def rand

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

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

下面是我的文本文件“songs.txt”的一个示例:

Billie Eilish-派对结束时
阿里安娜·格兰德-男朋友
TMC-无Scrubs
命运之子-说出我的名字
阿黛勒-你好
凯蒂·佩里-加利福尼亚女孩
BTS-家庭

以下是我的输出:

歌曲的第一个字母是:H,歌手是: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) 

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

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

我假设您将在某种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)

使用输入,考虑其他因素,如输入验证,因此确保用户输入仅是字母,没有数字/空格等。您可以包括一个计数器来跟踪得分。

< P>这里是一个解决方案,以一个生成器的形式,基于改组并用<代码>收益< /代码>实现。对于一个包含n个项目的列表,洗牌需要O(n)个时间,在迭代过程中摊销,以产生每首歌曲的固定时间。与“从列表中删除”解决方案相比,它的一个优点是生成器可以运行多次,如下面的代码所示。它将遍历整个序列,但如果您继续请求更多歌曲,则会产生不同的顺序

随机导入
歌曲列表=[
“Billie Eilish-派对结束时”,
“Ariana Grande-男朋友”,
“TMC-无Scrubs”,
“命运之子-说出我的名字”,
“阿黛尔-你好”,
“凯蒂·佩里-加利福尼亚女孩”,
“BTS-家庭”
]
def song_info():
随机播放(歌曲列表)
对于范围内的i(len(song_列表)):
产量列表[i]。拆分('-'))
def播放列表():
对于宋_info()中的(艺术家、标题):
打印(“歌曲的第一个字母是:“+title[0]+”,艺术家是:“+artist”)
播放列表()
打印(“太有趣了,我们再来一次吧!”)
播放列表()
显然,如果您预期歌曲的“数据库”不断增长,您可以通过读取文件而不是将其硬连接到代码中来填充
歌曲列表

将数据存储为artist&title的列表/元组,而不是要拆分的字符串,可能更有意义。这会将
song\u列表
song\u info()
生成器更改为:

歌曲列表=[
(“Billie Eilish”,“派对结束时”),
(“Ariana Grande”,“男朋友”),
(“TMC”,“无Scrubs”),
(“命运之子”,“说出我的名字”),
(“阿黛尔”,“你好”),
(“凯蒂·佩里”、“加利福尼亚女孩”),
(“BTS”、“家庭”)
]
def song_info():
随机播放(歌曲列表)
对于范围内的i(len(song_列表)):
产量表[i]

在我看来,哪一个更干净。

为什么不只是列表和循环通过洗牌版本呢?我不知道这一点,我会调查一下,谢谢!