Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 用节填充UITableView_Arrays_Swift_Uitableview_Dictionary - Fatal编程技术网

Arrays 用节填充UITableView

Arrays 用节填充UITableView,arrays,swift,uitableview,dictionary,Arrays,Swift,Uitableview,Dictionary,我正在尝试用节填充TableView。其中艺术家是章节名称,下面列出了该艺术家的所有歌曲。总共有100多名艺术家。像这样 FirstArtist - Song 1 - Song 2 SecondArtist - Song 1 - Song 2 OneMoreArtist... 我有一系列的物品 struct Song { let songName: String? let album: String? let artist: String? } var songs =

我正在尝试用节填充TableView。其中艺术家是章节名称,下面列出了该艺术家的所有歌曲。总共有100多名艺术家。像这样

FirstArtist
- Song 1
- Song 2

SecondArtist
 - Song 1
 - Song 2

OneMoreArtist...
我有一系列的物品

struct Song {

  let songName: String?
  let album: String?
  let artist: String?

}

var songs = [Song]()
还有一组所有艺术家的名字

var artists = [String]()
据我所知,要用部分填充tableView,我需要一个字典,以艺术家为键,以歌曲数组为值,如下所示

var toShow = [String : [Song]]()
所以,我试着循环

    for artist in artists {
      for song in songs {
        if song.artist == artist {

          toShow[artist] = [song]

//          toShow[artist]?.append(song)

        }
      }
    }
var artistWithSongs = [ArtistWithSongs]() 

     for artist in artists {
          for song in songs {
            if artist == song.artist {
              artistWithSongs.append(ArtistWithSongs(name: song, songs: [song]))
            }
          }
        }
但它不起作用

也许我走错了方向

在这种情况下,解决方案是什么

谢谢

更新

结巴

    struct ArtistWithSongs  { 
       let name: String
       let songs: [Song]

        init(name: String, songs: [Song]) {
      self.name = name
      self.songs = songs
    }   
}
试着循环

    for artist in artists {
      for song in songs {
        if song.artist == artist {

          toShow[artist] = [song]

//          toShow[artist]?.append(song)

        }
      }
    }
var artistWithSongs = [ArtistWithSongs]() 

     for artist in artists {
          for song in songs {
            if artist == song.artist {
              artistWithSongs.append(ArtistWithSongs(name: song, songs: [song]))
            }
          }
        }
但显然,我的循环变体是不正确的。现在我得到一个包含重复键的对象数组,每个键只有一首歌。看起来像

[Atrist1 : [Song1], Artist1 : [Song2], Artist1 : [Song3], ...]

我的问题是-创建循环的正确方法是什么,或者是否可以在字典中以某种方式合并具有相同键的对象以获得此
[Artist1:[Song1,Song2,Song3]

除了您的
Song
结构之外

struct Song {
  let songName: String?
  let album: String?
}
创建一个类似的艺术家

struct Artist { 
   let name:String
   let songs = [Song]()
}
然后创建一个数组

var artists = [Artist]()
let s1 = Song(songName:"name1",album:"alb1")
let s2 = Song(songName:"name2",album:"alb2")
let artist1 = Artist(name:"art",songs:[s1,s2])
artists.append(artist1)
numberOfSections
return中

artists.count
artists[section].songs.count 
numberOfRows
return中

artists.count
artists[section].songs.count 
cellForRowAt中
access

let song = artists[indexPath.section].songs[indexPath.row]

除了你的
歌曲
结构

struct Song {
  let songName: String?
  let album: String?
}
创建一个类似的艺术家

struct Artist { 
   let name:String
   let songs = [Song]()
}
然后创建一个数组

var artists = [Artist]()
let s1 = Song(songName:"name1",album:"alb1")
let s2 = Song(songName:"name2",album:"alb2")
let artist1 = Artist(name:"art",songs:[s1,s2])
artists.append(artist1)
numberOfSections
return中

artists.count
artists[section].songs.count 
numberOfRows
return中

artists.count
artists[section].songs.count 
cellForRowAt中
access

let song = artists[indexPath.section].songs[indexPath.row]

如果要将歌曲数组(
[Song]
)转换为字典(
[String:[Song]]]
),我建议使用函数式:

self.toShow = songs.reduce([String: [Song]]()) { acc, next in
  // mutable copy
  var acc = acc

  // since artist is optional we need to substitute it with non-optional value if it's nil
  let artist = next.artist ?? "Unknown Artist"

  // if dictionary already has this artist, then append the `next` song to an array
  if acc[artist] != nil {
    acc[artist]?.append(next)
  } else {
  // otherwise create new array
    acc[artist] = [next]
  }

  return acc
}
在表的数据源中,提供节数:

func numberOfSections(in tableView: UITableView) -> Int {
  return self.toShow.keys.count
}
然后您将面临一个问题:对于节中的行数,您需要知道该节代表哪位艺术家。因此,我建议您再使用一种结构,一组艺术家,以便保持各部分的顺序一致:

self.artists = Array(self.toShow.keys).sorted()
通过这种方式,您可以为表提供以下数量的节和行:

func numberOfSections(in tableView: UITableView) -> Int {
  return self.artists.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let artist = self.artists[section] // get the artist's name
  return self.toShow[artist]?.count ?? 0
}

如果要将歌曲数组(
[Song]
)转换为字典(
[String:[Song]]]
),我建议使用函数式:

self.toShow = songs.reduce([String: [Song]]()) { acc, next in
  // mutable copy
  var acc = acc

  // since artist is optional we need to substitute it with non-optional value if it's nil
  let artist = next.artist ?? "Unknown Artist"

  // if dictionary already has this artist, then append the `next` song to an array
  if acc[artist] != nil {
    acc[artist]?.append(next)
  } else {
  // otherwise create new array
    acc[artist] = [next]
  }

  return acc
}
在表的数据源中,提供节数:

func numberOfSections(in tableView: UITableView) -> Int {
  return self.toShow.keys.count
}
然后您将面临一个问题:对于节中的行数,您需要知道该节代表哪位艺术家。因此,我建议您再使用一种结构,一组艺术家,以便保持各部分的顺序一致:

self.artists = Array(self.toShow.keys).sorted()
通过这种方式,您可以为表提供以下数量的节和行:

func numberOfSections(in tableView: UITableView) -> Int {
  return self.artists.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let artist = self.artists[section] // get the artist's name
  return self.toShow[artist]?.count ?? 0
}

多亏了大家,我找到了一个解决方案,它对我想要实现的目标起到了作用。大致如此

let toShow = artistWithSongs.reduce([ArtistWithSongs](), { partialResult, artist in

    var dupe = partialResult.filter {$0.songName == group.name }.first
    if let dupeArtist = dupe {
        dupeArtist.songs?.append(contentsOf: artist.songs ?? [])
        return partialResult
    } else {
        var newPartialResult = partialResult
        newPartialResult.append(group)
        return newPartialResult
    }
})

多亏了大家,我找到了一个解决方案,它对我想要实现的目标起到了作用。大致如此

let toShow = artistWithSongs.reduce([ArtistWithSongs](), { partialResult, artist in

    var dupe = partialResult.filter {$0.songName == group.name }.first
    if let dupeArtist = dupe {
        dupeArtist.songs?.append(contentsOf: artist.songs ?? [])
        return partialResult
    } else {
        var newPartialResult = partialResult
        newPartialResult.append(group)
        return newPartialResult
    }
})

对不起,我以前没有提到过,我有很多艺术家,所以不可能手动将每个艺术家添加到[Artister]数组中。或者我误解了你的解决方案?谢谢,但我这么问是因为我的循环变体显然是不正确的。现在我得到一个包含重复键的对象数组,每个键只有一首歌。它看起来像[Atrist1:[Song1],Artist1:[Song2],Artist1:[Song3],…]。我的问题是-如何正确地创建循环,或者是否可以在字典中以某种方式合并具有相同键的对象以获得此[Artist1:[Song1,Song2,Song3]?抱歉,我以前没有提到过,我有很多艺术家,因此无法手动将每个艺术家添加到[Artist]数组中。或者我误解了你的解决方案?谢谢,但我这么问是因为我的循环变体显然是不正确的。现在我得到一个包含重复键的对象数组,每个键只有一首歌。它看起来像[Atrist1:[Song1],Artist1:[Song2],Artist1:[Song3],…]。我的问题是-如何正确地创建循环,或者是否可以在字典中以某种方式合并具有相同键的对象以获得此[Artist1:[Song1,Song2,Song3]?