Arrays 用节填充UITableView
我正在尝试用节填充TableView。其中艺术家是章节名称,下面列出了该艺术家的所有歌曲。总共有100多名艺术家。像这样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 =
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]?