将播放列表曲目分配给 3D 阵列
Assign Playlist-Tracks to 3D Array
所以我用 Spotify 的 API 和我 运行 尝试解决我遇到过的最复杂的问题。我有流派文本文件,例如"Chill" 或 "House"。在这些文件中,我有指向 Spotify-Playlists 的链接。这些行中的第一行代表我的这种类型的播放列表,例如:
myplalyist-ID
random1-ID
random2-ID ...
现在,由于这些链接指向播放列表,因此这些播放列表包含曲目。现在我想从那些 运行dom 播放列表中获取所有曲目并将其放入我的(过滤和添加曲目不是这里的问题,只是为了让你理解)。
现在我想我可以创建一个 3D 数组来处理这些轨道,例如:
1D: genre1 - genre2 - genre3
2D: playlist1 - playlist2 - playlist3
3D: tracks1 - tracks2 - tracks3
我希望你明白我的意思,我希望能够通过这样的方式访问播放列表曲目:
foreach(PlaylistTrack track in array[genre][playlist])
// filter & add "track"
所以我的处理方法如下:
//PlaylistTrack is the type in which Spotify stores a track within a Playlist
private List<PlaylistTrack>[,,] playlistTracks;//3D???
//this is to store the amount of playlists within a genre
private int[] playlistArray;
//int to save the amount of genre-files
private int fileCount;
//-----------------METHOD:
private void getTracks()
{
DirectoryInfo dir = new DirectoryInfo(this.path);//directory where genres are stored
this.fileCount = 0;
foreach (var file in dir.GetFiles("*.txt"))
{
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")//getting all genre textfiles
{
this.fileCount++;
}
}
this.playlistArray = new int[this.fileCount];
//i know using the foreach over and over is kinda bad and not preofessional,
//but i don't use c# on a daily base and i didn't knew how to get it done otherwise
int count = 0;
foreach (var file in dir.GetFiles("*.txt"))
{
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
int count2 = 0;
if (File.ReadAllText(file.FullName) != "")
{
using (StreamReader sr = new StreamReader(file.FullName))
{
string line = "";
while ((line = sr.ReadLine()) != null)
{
if (line != "")
{
count2++;
}
}
}
}
this.playlistArray[count] = count2;
count++;
}
}
for (int i = 0; i < this.fileCount; i++)
this.playlistTracks[i] = new List<PlaylistTrack>[this.playlistArray[i]]();
//here i'm stuck, how would i initialize the array, so it can holds a bunch of PlaylistTrack Items in "3rd row",
//accessable through [genre][playlist]
}
非常感谢任何帮助,因为我对此完全迷失了! :)
编辑:
这就是我的尝试:
//Setting File-Count to 0
this.fileCount = 0;
//Init new Dictionary
var allTracks = new Dictionary<string, Dictionary<string, List<PlaylistTrack>>>();
//Getting Directory where Genre-Files are
DirectoryInfo dir = new DirectoryInfo(this.path);
int count = 0;
//Looping through files in this Directory #1
foreach (var file in dir.GetFiles("*.txt"))
{
//Get only Genre-Files, not Track-Lists
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
count++;
}
}
//Init new string Array that will hold the Links to my Playlist for every genre
this.playlistLinks = new string[count];
//Looping through files in this Directory #2
foreach (var file in dir.GetFiles("*.txt"))
{
//Get only Genre-Files, not Track-Lists
if(file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
//If the Genre-File has content
if (File.ReadAllText(file.FullName) != "")
{
//Getting the Genre Name, by splitting the Genre-File-Name
string name = file.Name.Split(new string[] { ".txt" }, StringSplitOptions.None)[0];
//Reading the Genre-File
using (StreamReader sr = new StreamReader(file.FullName))
{
string line = "";
bool first = false;
//If the new line has content
while ((line = sr.ReadLine()) != null)
{
//If it's not the first line and the line is not ""
if (first && line != "")
{
//Splitting line to get Data
//split[0] = PlaylistID; split[1] = OwnerID
string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None);
//Getting Playlist Tracks and storing them in the Dictionary
//HERE HAPPENS THE ERROR
allTracks[name][split[0]] = this.getPlaylistTracks(split[1], split[0]);
//Looping through the Playlist-Tracks within the Dictionary
foreach (PlaylistTrack tr in allTracks [name][split[0]])
{
//If the Track is on Spotify's Servers
if (!tr.IsLocal)
{
//Filtering (not important here -> does work)
if (tr.AddedAt > time)
{
//Creating a string that holds Track's info
string write = tr.Track.Name + " // " + string.Join(",", tr.Track.Artists.Select(source => source.Name));
//Filtering tracks that i haven't listened to, by checking if track exists in "My Tracks.txt"
//(not important here -> does work)
if (!this.foundTrack(write))
{
//Adding collected Tracks to another List, sorted by Genre
//So all filtered Tracks from all Playlists within a genre are stored in one list
this.tracksToAdd[this.fileCount].Add(tr);
}
}
}
}
}
//If it's the first line where the line is not ""
if(!first && line != "")
{
string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None);
//Getting the PlaylistID of my Playlist
this.playlistLinks[this.fileCount] = split[0];
first = true;
}
}
}
}
//Increasing on every new Genre-File
this.fileCount++;
}
}
发生错误,我在代码中标记了它。错误消息是:
A "System.Collections.Generic.KeyNotFoundException" exception has
occurred in mscorlib.dll. Additional Information: The specified key
was not specified in the dictionary.
(大约 t运行 来自德语)
由于每个播放列表可以包含不同数量的歌曲,因此您不需要固定大小的 3D 矩阵 ([,,,]
),而是一组数组 ([][][]
)。您可以在 this question.
中了解它们之间的区别
也就是说,您可以使用 PlayListTrack[][][]
实现您想要的。
您可以使用 var allTracks = new PlayListTrack[amountOfGenres][][];
之类的东西,然后将 allTracks
的每一行初始化为 PlayListTrack[][]
,其大小是与该行匹配的流派的播放列表数量。最后,您可以将每个播放列表初始化为 PlayListTrack[]
,其大小是给定播放列表的歌曲数量。
无论如何,我建议您看一下 Dictionary<TKey, TValue> class,它允许您将唯一键(例如,流派的 ID)映射到值(例如,一个播放列表,它本身可以是一本字典)。
然后,你可以有这样的东西:
// Lists of tracks, indexed by their genre id (first string) and
// their playlist id (second string)
var allTracks = new Dictionary<string, Dictionary<string, List<PlayListTrack>>>();
// Examples
// Getting a genre, which is a Dictionary<string, List<PlayListTrack>>
var allJazzPlayLists = allTracks["jazz"];
// Getting a list of songs, which is a List<PlayListTrack>
var songs = allTracks["hip-hop"]["west side"];
所以我用 Spotify 的 API 和我 运行 尝试解决我遇到过的最复杂的问题。我有流派文本文件,例如"Chill" 或 "House"。在这些文件中,我有指向 Spotify-Playlists 的链接。这些行中的第一行代表我的这种类型的播放列表,例如:
myplalyist-ID
random1-ID
random2-ID ...
现在,由于这些链接指向播放列表,因此这些播放列表包含曲目。现在我想从那些 运行dom 播放列表中获取所有曲目并将其放入我的(过滤和添加曲目不是这里的问题,只是为了让你理解)。 现在我想我可以创建一个 3D 数组来处理这些轨道,例如:
1D: genre1 - genre2 - genre3
2D: playlist1 - playlist2 - playlist3
3D: tracks1 - tracks2 - tracks3
我希望你明白我的意思,我希望能够通过这样的方式访问播放列表曲目:
foreach(PlaylistTrack track in array[genre][playlist])
// filter & add "track"
所以我的处理方法如下:
//PlaylistTrack is the type in which Spotify stores a track within a Playlist
private List<PlaylistTrack>[,,] playlistTracks;//3D???
//this is to store the amount of playlists within a genre
private int[] playlistArray;
//int to save the amount of genre-files
private int fileCount;
//-----------------METHOD:
private void getTracks()
{
DirectoryInfo dir = new DirectoryInfo(this.path);//directory where genres are stored
this.fileCount = 0;
foreach (var file in dir.GetFiles("*.txt"))
{
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")//getting all genre textfiles
{
this.fileCount++;
}
}
this.playlistArray = new int[this.fileCount];
//i know using the foreach over and over is kinda bad and not preofessional,
//but i don't use c# on a daily base and i didn't knew how to get it done otherwise
int count = 0;
foreach (var file in dir.GetFiles("*.txt"))
{
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
int count2 = 0;
if (File.ReadAllText(file.FullName) != "")
{
using (StreamReader sr = new StreamReader(file.FullName))
{
string line = "";
while ((line = sr.ReadLine()) != null)
{
if (line != "")
{
count2++;
}
}
}
}
this.playlistArray[count] = count2;
count++;
}
}
for (int i = 0; i < this.fileCount; i++)
this.playlistTracks[i] = new List<PlaylistTrack>[this.playlistArray[i]]();
//here i'm stuck, how would i initialize the array, so it can holds a bunch of PlaylistTrack Items in "3rd row",
//accessable through [genre][playlist]
}
非常感谢任何帮助,因为我对此完全迷失了! :)
编辑: 这就是我的尝试:
//Setting File-Count to 0
this.fileCount = 0;
//Init new Dictionary
var allTracks = new Dictionary<string, Dictionary<string, List<PlaylistTrack>>>();
//Getting Directory where Genre-Files are
DirectoryInfo dir = new DirectoryInfo(this.path);
int count = 0;
//Looping through files in this Directory #1
foreach (var file in dir.GetFiles("*.txt"))
{
//Get only Genre-Files, not Track-Lists
if (file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
count++;
}
}
//Init new string Array that will hold the Links to my Playlist for every genre
this.playlistLinks = new string[count];
//Looping through files in this Directory #2
foreach (var file in dir.GetFiles("*.txt"))
{
//Get only Genre-Files, not Track-Lists
if(file.Name != "My Tracks.txt" && file.Name != "Tracks.txt")
{
//If the Genre-File has content
if (File.ReadAllText(file.FullName) != "")
{
//Getting the Genre Name, by splitting the Genre-File-Name
string name = file.Name.Split(new string[] { ".txt" }, StringSplitOptions.None)[0];
//Reading the Genre-File
using (StreamReader sr = new StreamReader(file.FullName))
{
string line = "";
bool first = false;
//If the new line has content
while ((line = sr.ReadLine()) != null)
{
//If it's not the first line and the line is not ""
if (first && line != "")
{
//Splitting line to get Data
//split[0] = PlaylistID; split[1] = OwnerID
string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None);
//Getting Playlist Tracks and storing them in the Dictionary
//HERE HAPPENS THE ERROR
allTracks[name][split[0]] = this.getPlaylistTracks(split[1], split[0]);
//Looping through the Playlist-Tracks within the Dictionary
foreach (PlaylistTrack tr in allTracks [name][split[0]])
{
//If the Track is on Spotify's Servers
if (!tr.IsLocal)
{
//Filtering (not important here -> does work)
if (tr.AddedAt > time)
{
//Creating a string that holds Track's info
string write = tr.Track.Name + " // " + string.Join(",", tr.Track.Artists.Select(source => source.Name));
//Filtering tracks that i haven't listened to, by checking if track exists in "My Tracks.txt"
//(not important here -> does work)
if (!this.foundTrack(write))
{
//Adding collected Tracks to another List, sorted by Genre
//So all filtered Tracks from all Playlists within a genre are stored in one list
this.tracksToAdd[this.fileCount].Add(tr);
}
}
}
}
}
//If it's the first line where the line is not ""
if(!first && line != "")
{
string[] split = line.Split(new string[] { " // " }, StringSplitOptions.None);
//Getting the PlaylistID of my Playlist
this.playlistLinks[this.fileCount] = split[0];
first = true;
}
}
}
}
//Increasing on every new Genre-File
this.fileCount++;
}
}
发生错误,我在代码中标记了它。错误消息是:
A "System.Collections.Generic.KeyNotFoundException" exception has occurred in mscorlib.dll. Additional Information: The specified key was not specified in the dictionary.
(大约 t运行 来自德语)
由于每个播放列表可以包含不同数量的歌曲,因此您不需要固定大小的 3D 矩阵 ([,,,]
),而是一组数组 ([][][]
)。您可以在 this question.
也就是说,您可以使用 PlayListTrack[][][]
实现您想要的。
您可以使用 var allTracks = new PlayListTrack[amountOfGenres][][];
之类的东西,然后将 allTracks
的每一行初始化为 PlayListTrack[][]
,其大小是与该行匹配的流派的播放列表数量。最后,您可以将每个播放列表初始化为 PlayListTrack[]
,其大小是给定播放列表的歌曲数量。
无论如何,我建议您看一下 Dictionary<TKey, TValue> class,它允许您将唯一键(例如,流派的 ID)映射到值(例如,一个播放列表,它本身可以是一本字典)。
然后,你可以有这样的东西:
// Lists of tracks, indexed by their genre id (first string) and
// their playlist id (second string)
var allTracks = new Dictionary<string, Dictionary<string, List<PlayListTrack>>>();
// Examples
// Getting a genre, which is a Dictionary<string, List<PlayListTrack>>
var allJazzPlayLists = allTracks["jazz"];
// Getting a list of songs, which is a List<PlayListTrack>
var songs = allTracks["hip-hop"]["west side"];