Как я могу функционально преобразовать массив объектов в другую структуру - PullRequest
0 голосов
/ 24 мая 2018

У меня есть массив шрифтов, каждый из которых имеет familyName и fontName.

Я хотел бы преобразовать их в массив кортежей в виде (familyName: String, fontNames: [String]).

Я чувствую, что должен быть простой функциональный способ сделать это, но я не могу решить это.Самое близкое, что у меня есть, это два вызова reduce: сначала в словарь, а затем в массив.

let dictionary = fonts.reduce(into [String : [String]]() ) { result, font in
    let array = result[font.fontFamily] ?? []
    result[fontFamily] = array + [font.fontName]
}

let array = dictionary(into: [(String, [String])]() ) { result, element in
    result.append( (element.key, element.value.sorted()) )
}.sorted { $0.0 < $1.0 }

Я также сортирую массив кортежей и массив fontNames в массиве.кортежей.

Есть ли способ избежать словарь-посредник?

Большое спасибо.

Обновление Я создал игровую площадку, чтобы показать sanjaykmwtРезультаты их предложений:

struct Font {
    let family: String
    let name: String
}

let fonts = [
    Font(family: "ABC", name: "abc"),
    Font(family: "ABC", name: "def"),
    Font(family: "ABC", name: "ghi"),
    Font(family: "XYZ", name: "xyz"),
    Font(family: "XYZ", name: "uvw")
]

let sortedFamily = fonts.sorted(by: { (lhs, rhs) -> Bool in
    return lhs.family < rhs.family
})

let dict = sortedFamily.map({["family":$0.family,
                              "fonts":$0.name]})

print("dict: \(dict)")

Вывод:

dict: [["family": "ABC", "fonts": "abc"], ["family": "ABC", "fonts": "def"], ["family": "ABC", "fonts": "ghi"], ["family": "XYZ", "fonts": "xyz"], ["family": "XYZ", "fonts": "uvw"]]

Ответы [ 3 ]

0 голосов
/ 24 мая 2018
    let sortedFamily = fonts.sorted(by: { (lhs, rhs) -> Bool in
        return lhs.family < rhs.family
    })

    let dict = sortedFamily.map({["family":$0.family,"fonts":$0.fonts.sorted()]})

попробуйте напечатать диктовку, вы получите все отсортировано

, если хотите еще короче, это может быть:

  let dict = fonts.sorted(by: { (lhs, rhs) -> Bool in
        return lhs.family < rhs.family
    }).map({["family":$0.family,"fonts":$0.fonts.sorted()]})
0 голосов
/ 25 мая 2018

Расширение (или сокращение!) Ответа Абделахада Дарвиша…

let tuples = Dictionary(grouping: fonts) { $0.family }
    .map { (familyName: $0.key, fontNames: $0.value.map { $0.name }) }

print(tuples)
[(familyName: "XYZ", fontNames: ["xyz", "uvw"]), (familyName: "ABC", fontNames: ["abc", "def", "ghi"])]
0 голосов
/ 24 мая 2018

если у вас есть массив Fonts с fontFamily, fontName

, вы можете сделать grouping, тогда map

 // Array Of Fonts Example

        let array = [Font.init(fontFamily: "Cago", fontName: "AA"),
                                     Font.init(fontFamily: "Cago", fontName: "CCCC"),
                                     Font.init(fontFamily: "Mango", fontName: "AAsss"),
                                      Font.init(fontFamily: "Mango", fontName: "mngoo")]

         // Grouping

        let groupedByFamilayName = Dictionary.init(grouping: array) {$0.fontFamily}

        // Map
        let arrayOfTuple =  groupedByFamilayName.map { (key,array) -> (String,[String]) in
                            return (key,array.map({$0.fontName}))
                        }

     print(arrayOfTuple)
...