Reputation: 19
I have a txt file with a list of artists, songs, and genres in the following format:
song 1
genre 1
artist 1
song 2
genre 2
artist 2
etc.
I'm given an artists name and if the artist is in the file I have to return the name of their song. The code I've managed to write is:
afile = open('music.txt')
header = afile.readline()
artists = afile.readlines()
afile.close()
for art in artists:
if art == artist:
How could I get the name of the song that is two lines above the artists name? It's also possible that an artists appears several times with different songs.
Upvotes: 1
Views: 362
Reputation: 173
All answers until now are valid, but they do rely on the fact that the format is always 4 lines. Here is code that also does work if there is missing data or there is more data:
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})
This is also extendable if your format later includes another key like 'album'.
If you're using python3.10 you could look into pattern matching to further simplify the code.
Upvotes: 0
Reputation:
Start at the second element (as that is where the first artist is) and scan every 4th element for the artist. If the i-th
element of linelist
matches artist
, print the song (which is at i-2
).
for i in range(2, 100, 4):
if linelist[i] == artist:
print(linelist[i-2])
Upvotes: 0
Reputation: 25500
First, read your file into a list. I'm assuming the format of your file is fixed: it contains
Note that since there doesn't seem to be a header, you don't need the initial header = afile.readline()
Let's say you read all the lines of your file into a list called 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
Now, you know that
lines
list to take every fourth line, starting at the first line and save it as a list called songs
songs = lines[0::4]
genres = lines[1::4]
artists = lines[2::4]
Now, we can zip()
these lists to iterate over them simultaneously, and print the songs for the artists that match the one we're looking for:
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
If you were doing this for a bunch of artists, I'd recommend you read the data into a dictionary (or a collections.defaultdict
) first. Then, you can look up the value of the dictionary for the given artist and this will be much faster than looping over the lists.
To account for the case when a single artist can have multiple songs, we're going to use a dictionary where the keys are the artist's name, and values are a list containing all the songs by them.
import collections
lookup_dict = collections.defaultdict(list)
for artist, genre, song in zip(artists, genres, songs):
lookup_dict[artist].append((genre, song))
Then, all you need to do is:
for genre, song in lookup_dict[look_for_artist]:
print(song, genre)
You can remove the need to read the entire file into a list and then process it into a dictionary by reading the file line-by-line in groups of four lines, but I will leave that as an exercise for you.
Upvotes: 1
Reputation: 1054
Assuming that each artist has only one song (or you are searching for the first match) you could solve it like this:
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"
Upvotes: 0