我正在尝试用部分填充TableView。下面列出了一位歌手,该歌手是乐段名称,该歌手的所有歌曲都在下面列出。总计超过100位艺术家。像这样
FirstArtist
- Song 1
- Song 2
SecondArtist
- Song 1
- Song 2
OneMoreArtist...
我有一个对象数组Song
struct Song {
let songName: String?
let album: String?
let artist: String?
}
var songs = [Song]()
以及所有艺术家姓名的数组
var artists = [String]()
据我所知,要用部分填充tableView,我需要一个Dictionary,以Artist作为键,并将Songs数组作为值,
var toShow = [String : [Song]]()
所以,然后我要循环播放
for artist in artists {
for song in songs {
if song.artist == artist {
toShow[artist] = [song]
// toShow[artist]?.append(song)
}
}
}
但这不起作用。
可能我走错了路。
在这种情况下有什么解决方案?
谢谢
更新
做出构图
struct ArtistWithSongs {
let name: String
let songs: [Song]
init(name: String, songs: [Song]) {
self.name = name
self.songs = songs
}
}
并尝试循环
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], ...]
我的问题是-进行循环的正确方法是什么,或者有可能以某种方式在Dictionary中合并具有相同键的对象以获得此[Artist1 :[Song1, Song2, Song3]]
?
答案 0 :(得分:2)
感谢大家,我找到了一个解决方案here,它可以解决我想要达到的目标。大概是这样
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
}
})
答案 1 :(得分:1)
除了您的#ifndef NAMESPACE_IN_NAMESPACE
#error "NAMESPACE_IN_NAMESPACE not defined"
#endif
}
#undef NAMESPACE_NAME
#undef NAMESPACE_NAME_STRING
#undef NAMESPACE_IN_NAMESPACE
结构
Song
创建一个struct Song {
let songName: String?
let album: String?
}
喜欢的人
Artist
然后创建一个数组
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
在artists.count
中返回
numberOfRows
在artists[section].songs.count
访问中
cellForRowAt
答案 2 :(得分:1)
如果要将歌曲([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
}