Struct 将每个可识别的结构对象属性按categoryName排序放入列表中

Struct 将每个可识别的结构对象属性按categoryName排序放入列表中,struct,foreach,swiftui,Struct,Foreach,Swiftui,我觉得我在这里遗漏了一些明显的东西,但我已经被困在这个问题上好几天了,似乎找不到答案 1.)我使用的是一个单独的swift文件,该文件具有一个可识别的结构,该结构具有两个结构属性name&categoryName。(旁注,我使用var而不是let-in对象,因为行不能用.onMove修饰符作为常量重新排列) 2.)在swiftui文件中,我使用以下代码构建列表,使用嵌套的ForEach循环提取categoryName,将其添加到节头,然后使用另一个循环输出项目 //List code

我觉得我在这里遗漏了一些明显的东西,但我已经被困在这个问题上好几天了,似乎找不到答案

1.)我使用的是一个单独的swift文件,该文件具有一个可识别的结构,该结构具有两个结构属性name&categoryName。(旁注,我使用var而不是let-in对象,因为行不能用.onMove修饰符作为常量重新排列)

2.)在swiftui文件中,我使用以下代码构建列表,使用嵌套的ForEach循环提取categoryName,将其添加到节头,然后使用另一个循环输出项目

    //List code

 NavigationView {
            List {
                ForEach(items) { currentItem in
                    Section(header: Text(currentItem.categoryName)){
                        ForEach(items) { currentItem in
                             NavigationLink(destination: ItemDetail(itemData: currentItem)){ ItemRow(item: currentItem)

                            }
                        }

不幸的是,我得到的是一个可笑的结果

我在节标题中获得我的categoryName,并在下面列出我的项目。事实上,我得到了下面列出的所有项目,无论类别如何。然后,以一种非常混乱的方式,这些部分的打印次数将与我的对象数组中的行的打印次数完全相同

在这个例子中,我有6行,所以我有6行。然而,在两个类别名称字符串“衣服”和“电子产品”中,它们将分别打印3次

感觉有一种简单的方法可以“为items.categoryName中的每个categoryName添加一个标题到部分并列出相应的名称”——但我不会破解这个方法


希望这里有人能指出我做错了什么

您有一个平面数组,只需在其中迭代几次,所以结果也是平面乘以几次

好的,对于您选择的模型,即
,您尝试实现的结果可以通过以下方式实现

List {
    ForEach(Array(Set(items.compactMap{ $0[keyPath: \.categoryName] })), id: \.self) { category in
        Section(header: Text(category)) {
            ForEach(items.filter { $0.categoryName == category }) { currentItem in
                 NavigationLink(destination: Text("ItemDetail(itemData: currentItem)")){ Text("\(currentItem.name)") }
                }
            }
        }
}
.listStyle(GroupedListStyle())

然而,我会为
项选择不同的模型,即字典为
[categoryName:Item]

您有一个平面数组,只需重复它几次,所以结果也是平面乘以几次

好的,对于您选择的模型,即
,您尝试实现的结果可以通过以下方式实现

List {
    ForEach(Array(Set(items.compactMap{ $0[keyPath: \.categoryName] })), id: \.self) { category in
        Section(header: Text(category)) {
            ForEach(items.filter { $0.categoryName == category }) { currentItem in
                 NavigationLink(destination: Text("ItemDetail(itemData: currentItem)")){ Text("\(currentItem.name)") }
                }
            }
        }
}
.listStyle(GroupedListStyle())

但是,我会为
项选择不同的模型,即字典为
[categoryName:Item]
您可以按类别对数组进行分组:

let sections = Dictionary(grouping: items) { $0.categoryName }
然后你可以像这样使用它:

var keys: [String] = { sections.map {$0.key} }

var body: some View {
    List {
        ForEach(keys, id: \.self) { section in
            Section(header: Text(section)){
                ForEach(self.sections[section] ?? []) { currentItem in
                    Text(currentItem.name)
                }
            }
        }
    }
}

请注意,我已将您的代码简化为在我的计算机上运行,但更改不会影响答案

您可以按类别对阵列进行分组:

let sections = Dictionary(grouping: items) { $0.categoryName }
然后你可以像这样使用它:

var keys: [String] = { sections.map {$0.key} }

var body: some View {
    List {
        ForEach(keys, id: \.self) { section in
            Section(header: Text(section)){
                ForEach(self.sections[section] ?? []) { currentItem in
                    Text(currentItem.name)
                }
            }
        }
    }
}

请注意,我已经简化了您的代码以在我的机器上运行,但更改不会影响答案

我想指出,Asperi和@Mojtaba的答案都有效。关键的区别在于Asperi的代码为每个项目正确地使用了列表行(项目包含在单独的行中),而Mojtaba下面的代码,即使对错误进行了一些修改,也没有相同的结构。我要感谢你们在这方面的解释和帮助!非常感谢。我想指出,Asperi和@Mojtaba的回答都是有效的。关键的区别在于Asperi的代码为每个项目正确地使用了列表行(项目包含在单独的行中),而Mojtaba下面的代码,即使对错误进行了一些修改,也没有相同的结构。我要感谢你们在这方面的解释和帮助!非常感谢。