【问题标题】:NSPredicate Filtered childs in arrayNSPredicate 过滤数组中的孩子
【发布时间】:2015-02-14 13:59:49
【问题描述】:

您好,我正在使用新语言 Apple Swift 并使用 NSArray:

[
    {
        "Section" : "Title1",
        "Items" :
        [
            {"Nr" : "101"},
            {"Nr" : "201"},
            {"Nr" : "301"},
            {"Nr" : "401"}
        ]
    },
    {
        "Section" : "Title2",
        "Items" :
        [
            {"Nr" : "102"},
            {"Nr" : "202"},
            {"Nr" : "302"}
        ]
    },
    {
        "Section" : "Title3",
        "Items" :
        [
            {"Nr" : "1102"},
            {"Nr" : "2102"},
            {"Nr" : "3102"}
        ]
    }
]

我想使用搜索,只显示找到的内容

据我了解,我必须在 swift 中使用“filteredArrayUsingPredicate”和 NSPredicate,所以我的示例是:

var arr:NSArray = [...] // My array sample goes here
var pre:NSPredicate = NSPredicate(format: "ANY Items.Nr BEGINSWITH[c] %@", argumentArray: ["20"]) // We a going to search "20" in /Items/Nr

var result:NSArray = arr.filteredArrayUsingPredicate(pre)

这是正确的,但结果不是我需要的:

result = 
[
    {
        "Section" : "Title1",
        "Items" :
        [
            {"Nr" : "101"},
            {"Nr" : "201"},
            {"Nr" : "301"},
            {"Nr" : "401"}
        ]
    },
    {
        "Section" : "Title2",
        "Items" :
        [
            {"Nr" : "102"},
            {"Nr" : "202"},
            {"Nr" : "302"}
        ]
    }
]

向我展示所有包含 Imtes 且 Nr 以“20”开头的部分

我的问题是如何在项目中进行过滤?我需要的结果是:

result = 
[
    {
        "Section" : "Title1",
        "Items" :
        [
            {"Nr" : "201"}
        ]
    },
    {
        "Section" : "Title2",
        "Items" :
        [
            {"Nr" : "202"}
        ]
    }
]

我尝试使用 SUBQUERY:

"SUBQUERY(Items, $x, $x.Nr BEGINSWITH[c] %@).@count > 0"

但这给我的回报是一样的,如果它可以计算项目,那么我认为它可以显示我找到的项目/编号,但我不知道如何正确地写这个。 :)

【问题讨论】:

    标签: swift filter nsarray nspredicate


    【解决方案1】:

    哦,等一下。我刚刚重新阅读了您的问题,现在正在编辑

    回答您过滤子数组的要求。您的数据模型变得过于复杂,无法继续使用通用对象。您应该考虑使用自定义对象设置实际的数据结构。然后,您可以将大量工作卸载到这些对象上,而不是将所有工作放在一个地方。

    只是试图找到执行此操作的最佳方法(无需自定义数据模型)。​​

    附:制作自定义数据模型:)

    好的,我们开始

    通过将您的通用数据包装到一个结构中,我使这变得容易多了...

    struct Item {
        let section: String
        let items: [[String: String]]
    }
    

    如果每个字典只有一个键并且总是相同的字典数组,这仍然是错误的。实际上它应该只是一个字符串数组。

    无论如何...

    像这样创建数组...

    let items: [Item] = [
        Item(section: "Title1", items: [["Nr" : "101"], ["Nr" : "201"], ["Nr" : "301"], ["Nr" : "401"]]),
        Item(section: "Title2", items: [["Nr" : "102"], ["Nr" : "202"], ["Nr" : "302"]]),
        Item(section: "Title3", items: [["Nr" : "1102"], ["Nr" : "2102"], ["Nr" : "3102"]])
    ]
    

    或者从您存储的数据中获取。

    然后过滤并映射到一个新的数组中……

    let filteredMappedArray = items.filter {
        // this filters the array so that only its containing "20..." are in it.
        for dictionary in $0.items {
            if let numberString = dictionary["Nr"] {
                if (numberString.hasPrefix("20")) {
                    return true
                }
            }
        }
        return false
    }.map {
        // This maps the array and removes anything that isn't "20..." from the items.
        Item(section: $0.section, items: $0.items.filter {
            numberDictionary in
            if let numberString = numberDictionary["Nr"] {
                return numberString.hasPrefix("20")
            }
            return false
        })
    }
    

    然后我记录了结果...

    for item in filteredMappedArray {
        println("Section: \(item.section) - Items: \(item.items)")
    }
    

    得到了这个结果……

    Section: Title1 - Items: [[Nr: 201]]
    Section: Title2 - Items: [[Nr: 202]]
    

    可能有更好/更简单的方法将所有内容组合成一个函数,但这是我能找到的最简单的方法。

    如果你能改变你的字典数组的话……

    如果项目可以定义为...

    struct Item {
        let section: String
        let items: [String]
    }
    

    那么filter-map函数就会变成……

    let filteredMappedArray = items.filter {
        // this filters the array so that only its containing "20..." are in it.
        for numberString in $0.items {
            if (numberString.hasPrefix("20")) {
                return true
            }
        }
        return false
    }.map {
        // This maps the array and removes anything that isn't "20..." from the items.
        Item(section: $0.section, items: $0.items.filter {$0.hasPrefix("20")})
    }
    

    通过将字典数组更改为字符串数组,您可以消除不必要的复杂性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多