Help with erase function in unordered_map

I just started learning about unordered_map, and from my understanding, it erases the key and the value based on the key. My question would be how I would able to erase a value of the unordered_map. I have two unordered_map and for librarySong I can simply call the member function erase to remove the songID number. My problem would be libraryID, I am unsure how I can erase a song given that the key is a string and the value is the songID.

Song
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 class Song{

	public:
		// Default constructor
		Song(): songName(""), artistName(""), albumName("") {
			//Left blank intentionally
		}
		// Destructor	
		~Song() {};
		// Sets a name for the song
		void setSongName(string aSong){

			songName = aSong;
		}
		// Gets the name of the song
		string getSongName(){

			return songName;
		}
		// Sets the artist name of the song
		void setArtistName(string anArtist){

			artistName = anArtist;
		}
		// Gets the name of the artist
		string getArtistName(){

			return artistName; 
		}
		// Sets the album name of the song
		void setAlbum(string anAlbum){

			albumName = anAlbum;
		}
		// Gets the album name of the song
		string getAlbum(){

			return albumName;
		}

	private:
		string songName;
		string artistName;
		string albumName;
};


SongWrapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class SongWrapper : public Song{

	public:
		// Default constructor
		SongWrapper() : iterativeID(0), numOfPlays(0){
			// left blank
		} 
		// Destructor
		~SongWrapper() {};

		//create an ID
		unsigned int createID(){

			return iterativeID++;
		}
		//Get the ID of the song
		unsigned int getID(){

			return iterativeID;
		}
		// Sets the number of plays of a song
		void setNumOfPlays(int plays){

			numOfPlays = plays;
		}
		// Gets the number of plays of a song
		unsigned int getNumOfPlays(){

			return numOfPlays;
		}

	private:
		unsigned int iterativeID;
		unsigned int numOfPlays;
};


Library
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class Library{

	public:
		// Default constructor
		Library(){};
		// Destructor
		~Library(){};
		//Create a song with Song details
		SongWrapper* createSong(string song, string artist, string album);
		//removes the identifier
		// Plays a song a number of times
		unsigned int playSong(unsigned int numberOfPlays);
		// Checks if the song exist
		bool doesSongExist(string theSong);
		// Checks if the ID of the song exist
		bool doesIdentifierExist(int identifier);
		// Gets the details of the song
		string getSongDetails(SongWrapper* aSong);
		// Adds song into the library
		void addSongIntoLibrary(SongWrapper* aSong);
		// Remove song given the song ID number
		void removeSongFromLibrary(unsigned int identifier);

	private:
                // SongID = key, 
		unordered_map<int, SongWrapper*>librarySongs; // key = ID in the library
               // SongID = value
		unordered_map<string, int>libraryID; // key = Song name "Ex:Songname ArtistName AlbumName"

};

unsigned int Library::playSong(unsigned int numberOfPlays){

	SongWrapper* aSong = new SongWrapper;
	if(doesIdentifierExist(aSong->getID()) == false){
		return 0;
	}
	aSong->setNumOfPlays(aSong->getNumOfPlays() + numberOfPlays);
	return aSong->getNumOfPlays();
}

bool Library::doesIdentifierExist(int identifier){

	if(librarySongs.find(identifier) == librarySongs.end()){
		cout << "No song with identifier #" << identifier << " exist in your library." << endl;
		return false;
	}
	return true;
}

bool Library::doesSongExist(string theSong){

	if(libraryID.find(theSong) == libraryID.end()){
		return false;
	}
	return true;
}

SongWrapper* Library::createSong(string song, string artist, string album){

	SongWrapper* aSong = new SongWrapper;
	aSong->setSongName(song);
	aSong->setArtistName(artist);
	aSong->setAlbum(album);
	aSong->setNumOfPlays(0);
	aSong->createID();
	return aSong;
}

string Library::getSongDetails(SongWrapper* aSong){

	string songString;
	songString = aSong->getSongName() + aSong->getArtistName() + aSong->getAlbum();
	return songString;
}

void Library::addSongIntoLibrary(SongWrapper* aSong){

	string song,artist,album, theSong;
	theSong = getSongDetails(aSong);
	if(doesSongExist(theSong) == true){
		return;
	}
	pair<int, SongWrapper*>songWrapperPointer (aSong->getID(), createSong(song,artist,album));
	pair<string, int>songDetail (getSongDetails(aSong), aSong->getID());
	librarySongs.insert(songWrapperPointer);
	libraryID.insert(songDetail);
}
// This function takes a SongID and removes that song from the playlist. 
// Since I have two maps I have to erase song in both maps given the songID
void Library::removeSongFromLibrary(unsigned int identifier){

	librarySongs.erase(identifier);
	libraryID.erase() // <--- Not sure how to implement this
}
Last edited on
closed account (48T7M4Gy)
http://www.cplusplus.com/reference/unordered_map/unordered_map/erase/

The sample shows the variety of erase() options. If the key is a string you can take advantage of substr() and other <string> functionality combined with map find() to filter the keys, say if you just entered the first few characters in the song title etc.
Last edited on
@kemort I was looking through that, but in those example it erases given a key. My key is the song ID number which is my key value of my first map librarySong. My problem is my second map libraryID where my key is the songDetails and the songID is the value. Since my removeSongFromLibraray(unsigned int identifier) takes the songID as a parameter I am able to do librarySongs.erase(identifier);, but for libraryID it would not work the same.


EDIT:
1
2
3
4
5
6
7
8
9
10
void Library::removeSongFromLibrary(unsigned int identifier){

	if(doesIdentifierExist(identifier) == false){
		return;
	}
	string songString;
	songString = getSongDetails(librarySongs.at(identifier));
	librarySongs.erase(identifier);
	libraryID.erase(songString);
}

Would my above code for erase work?
Last edited on
closed account (48T7M4Gy)
Would my above code for erase work?


I haven't run you code but I guessed that was what you might be trying to do.
On face value it looks like what you have done is correct - specify the song, find it in the library and erase it. All while the keys in each case differ so you need to cross-reference. Have you tested it out - that's the important step?

BTW I wouldn't mix up 'library' and 'songs' in any functions or variable names
'librarySongs' is bad, to my mind - just 'library' does the job. It's important because you may have libraries, or playlists which don't contain songs but the songs are still available to use. Or alternatively you want to clear out songs
entirely.
removeSong(), the Library is implicit. All you have to resolve is whether the song is completely erased or just flagged as not available. (I realise this might be more than what your assignment requires, so it's up to you needless to say.)
I haven't tested my code as of now, but I'm just trying to figure out the logic behind each function. My remove would take out that key and value, so flag to keep track if it's available wouldn't be necessary. Thanks for the help.
Topic archived. No new replies allowed.