我有以下代码,我正在尝试打印booksAssigned和booksAssignedDue,具体取决于ChaptersToRead
var books:[String] = ["Hobbit","LOTR","Fellowship"]
var chaptersToRead:[[Int]] = [[1],[1,2],[2]]
var booksAssigned:[String] = []
var booksAssignedDue:[String] = []
for (index, chapters) in chaptersToRead.enumerated() {
if chapters.contains(1) {
booksAssigned.append(books[index])
}
else
{
booksAssignedDue.append(books[index])
}
}
我的预期输出是
print(booksAssigned) = ["Hobbit","LOTR"]
print(booksAssignedDue) = ["LOTR","Fellowship"]
但我得到了这个
print(booksAssigned) = ["Hobbit","LOTR"]
print(booksAssignedDue) = ["Fellowship"]
我做错了什么?
答案 0 :(得分:4)
试试这个:
for (index, chapters) in chaptersToRead.enumerated() {
if chapters.contains(1) {
booksAssigned.append(books[index])
}
//You should not use `else` here.
if chapters.contains(2) {
booksAssignedDue.append(books[index])
}
}
如果您在标记的位置使用else
,则添加到booksAssigned
的图书无法添加到booksAssignedDue
。
答案 1 :(得分:1)
zip(_:_:)
当你处理具有成对元素关系的序列(/有序集合)时(例如books
中的书和chaptersToRead
中的相关章节列表),它是合适且有用的使用全局zip(_:_:)
函数来处理压缩序列:
// no need to explicitly annotate type: it will be correctly inferred
let books = ["Hobbit", "LOTR", "Fellowship"]
let chaptersToRead = [[1], [1,2], [2]]
// apply a flatMap over the zipped collection of the books and the
// associated chapters to read, with a 'nil' conditional for the '1'
// and '2' inclusions for booksAssigned and booksAssignedDue, respectively.
let booksAssigned = zip(books, chaptersToRead)
.flatMap { $1.contains(1) ? $0 : nil }
let booksAssignedDue = zip(books, chaptersToRead)
.flatMap { $1.contains(2) ? $0 : nil }
print(booksAssigned) // ["Hobbit", "LOTR"]
print(booksAssignedDue) // ["LOTR", "Fellowship"]
使用这种方法,您不需要预先声明并重复附加到可变数组,但可以使用压缩序列上的booksAssigned
操作直接实例化flatMap
数组。您还可以避免使用从外部“源”接收的索引显式访问数组的索引(在这种情况下,是另一个的索引,尽管是相关的数组),这种方法可能导致危险,因为索引是使用前未使用过。
另请注意,我已将上面的所有数组更改为不可变项:除非您确定要改变属性/变量,否则最好使用不可变项(可能您希望在应用此实现的实际上下文中使用不可变项) )。
使用密切相关的序列时的另一个见解是,您可能需要考虑简单地以适当的类型连接这些成对的元素(例如,它涵盖了与书籍相关的boks标题和章节),这将允许简单地使用具有此类元素的单个数组,而不是几个单独的数组。
struct Book {
let title: String
let chaptersToRead: [Int]
}
/* possibly `chaptersToRead` should be a mutable property rather
than an immutable one, in case you plan to mutate it for an
existing `Book` instance. */
let books = [Book(title: "Hobbit", chaptersToRead: [1]),
Book(title: "LOTR", chaptersToRead: [1, 2]),
Book(title: "Fellowship", chaptersToRead: [2])]
let booksAssigned = books
.flatMap { $0.chaptersToRead.contains(1) ? $0.title : nil }
let booksAssignedDue = books
.flatMap { $0.chaptersToRead.contains(2) ? $0.title : nil }
print(booksAssigned) // ["Hobbit", "LOTR"]
print(booksAssignedDue) // ["LOTR", "Fellowship"]
或者,使用此方法,您可能希望使用已过滤的Book
个实例而不仅仅是title
个属性:
let booksAssigned = books.filter { $0.chaptersToRead.contains(1) }
let booksAssignedDue = books.filter { $0.chaptersToRead.contains(2) }
如果您将与给定Book
个实例数组关联的标题设置为String
个实例数组,则可以在.map { $0.title }
上应用[Book]
轻松获取这些标题。数组。