#python #file #txt
Вопрос:
У меня есть файл 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:
Как я мог узнать название песни, которое находится на две строчки выше имени исполнителя? Также возможно, что исполнитель появляется несколько раз с разными песнями.
Комментарии:
1. Что делать, если у исполнителя несколько песен?
2. зачем вам это нужно
header
? У вас нет никакого заголовка в файле примера
Ответ №1:
Сначала прочитайте свой файл в списке. Я предполагаю, что формат вашего файла исправлен: он содержит
- Строка, указывающая название песни
- Строка, указывающая жанр
- Строка, указывающая исполнителя
- Пустая строка
- Повторять
Обратите внимание, что, поскольку заголовка, похоже, нет, вам не нужен начальный 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)
Вы можете избавиться от необходимости считывать весь файл в список, а затем обрабатывать его в словаре, читая файл построчно группами по четыре строки, но я оставлю это в качестве упражнения для вас.
Ответ №2:
Предполагая, что у каждого исполнителя есть только одна песня (или вы ищете первое совпадение), вы могли бы решить ее следующим образом:
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"
Ответ №3:
Начните со второго элемента (так как именно там находится первый исполнитель) и сканируйте каждый 4-й элемент в поисках исполнителя. Если i-th
элемент linelist
совпадает artist
, выведите песню (которая находится по адресу i-2
).
for i in range(2, 100, 4):
if linelist[i] == artist:
print(linelist[i-2])
Комментарии:
1.
afile.readlines()
уже дает вам список2. @PranavHosangadi Хорошая мысль.
Ответ №4:
Все ответы до сих пор действительны, но они основаны на том факте, что формат всегда составляет 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})
Это также можно расширить, если ваш формат позже будет включать другую клавишу, например «альбом».
Если вы используете python3.10, вы можете изучить сопоставление шаблонов для дальнейшего упрощения кода.