2017-02-12 52 views
0

所以我使用Spotify的API进行实验,并遇到了我遇到过的最复杂的问题。我有Genre文本文件,例如“寒意”或“房子”。在这些文件中,我有Spotify-Playlists的链接。其中第一个行代表我对这个流派播放列表,例如:将播放列表分配到3D阵列

myplalyist-ID 
random1-ID 
random2-ID ... 

现在,因为这些链接指向的播放列表,播放那些包含的曲目。现在我想从这些随机播放列表中获取所有曲目,并将其融入我的过滤器中(过滤和添加曲目在这里不是问题,只是为了让您理解)。 现在,我想我可以创建一个三维阵列来处理这些曲目,如:

1D: genre1 - genre2 - genre3 
2D: playlist1 - playlist2 - playlist3 
3D: tracks1 - tracks2 - tracks3 

我希望你明白我的意思,我希望能够访问playlisttracks槽是这样的:

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++; 
    } 
} 

错误发生,在那里我的代码标记它。差错信息是:已经 出现在mscorlib.dll

A “System.Collections.Generic.KeyNotFoundException” 异常。附加信息:指定的键 未在字典中指定。

(从德国大致翻译)

回答

1

由于每个播放列表可以具有不同数量的歌曲,则不需要固定的大小的3D矩阵([,,,]),但数组的数组([][][])。您可以在this question中阅读它们之间的区别。

这就是说,你可以使用PlayListTrack[][][]实现你想要的。 你可能有类似var allTracks = new PlayListTrack[amountOfGenres][][];的东西,然后将allTracks的每一行初始化为PlayListTrack[][],其大小是与该行匹配的流派的播放列表的数量。最后,您可以将每个播放列表初始化为PlayListTrack[],其大小是给定播放列表的歌曲数量。

无论如何,我建议你看一下Dictionary<TKey, TValue>类,它允许你将一个唯一的键(例如,一个流派的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"]; 
+0

感谢,伟大的答案!我认为这是我正在寻找的。我添加了我在OP中尝试的代码:也许你可以看看它,并告诉我为什么会出现这个错误,以及我如何修复它。 –

+0

发生错误是因为'allTracks [name] [split [0]]'尝试获取不存在的allTracks [name]'。在该行之前,如果它不存在,则应该创建嵌套字典:'if(!allTracks.ContainsKey(name)){allTracks [name] = new Dictionary >();}'。然后,你可以调用'allTracks [name] [split [0]] = this.getPlaylistTracks(split [1],split [0]);',假设你的'getPlaylistTracks(string,string)'方法返回一个'List ' – Sam