Nutriments are now iterable
This commit is contained in:
@@ -2,7 +2,7 @@ import Foundation
|
|||||||
import Units
|
import Units
|
||||||
|
|
||||||
@dynamicMemberLookup
|
@dynamicMemberLookup
|
||||||
public struct Nutriments: Codable, Sendable {
|
public struct Nutriments: Codable, Sendable, Sequence {
|
||||||
// We separate values (Doubles) and units (Strings) for efficient, thread-safe storage
|
// We separate values (Doubles) and units (Strings) for efficient, thread-safe storage
|
||||||
private let values: [String: Double]
|
private let values: [String: Double]
|
||||||
private let units: [String: String]
|
private let units: [String: String]
|
||||||
@@ -49,6 +49,43 @@ public struct Nutriments: Codable, Sendable {
|
|||||||
let kebabName = member.camelCaseToKebabCase()
|
let kebabName = member.camelCaseToKebabCase()
|
||||||
return Nutrient(name: kebabName, values: values, units: units)
|
return Nutrient(name: kebabName, values: values, units: units)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Sequence Conformance
|
||||||
|
// Allows: nutriments.forEach { nutrient in ... }
|
||||||
|
public func makeIterator() -> AnyIterator<Nutrient> {
|
||||||
|
// 1. Collect all keys from values and units
|
||||||
|
let allKeys = Set(values.keys).union(units.keys)
|
||||||
|
|
||||||
|
// 2. Extract unique base names (e.g., "energy-kcal_100g" -> "energy-kcal")
|
||||||
|
let baseNames = allKeys.compactMap { key -> String? in
|
||||||
|
// Filter out keys that are not nutrient properties
|
||||||
|
guard !key.isEmpty else { return nil }
|
||||||
|
|
||||||
|
// Remove common suffixes to find the "root" nutrient name
|
||||||
|
let suffixes = [
|
||||||
|
"_100g", "_serving", "_unit", "_value", "_prepared", "_label",
|
||||||
|
]
|
||||||
|
var name = key
|
||||||
|
|
||||||
|
// Sort suffixes by length (descending) to avoid partial matches
|
||||||
|
for suffix in suffixes {
|
||||||
|
if let range = name.range(of: suffix) {
|
||||||
|
name.removeSubrange(range)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Create a unique sorted list
|
||||||
|
let uniqueNames = Set(baseNames).sorted()
|
||||||
|
var iterator = uniqueNames.makeIterator()
|
||||||
|
|
||||||
|
// 4. Return an iterator that produces `Nutrient` views
|
||||||
|
return AnyIterator {
|
||||||
|
guard let name = iterator.next() else { return nil }
|
||||||
|
return Nutrient(name: name, values: self.values, units: self.units)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Nutrient View
|
// MARK: - Nutrient View
|
||||||
|
|||||||
1
jsonResults.json
Normal file
1
jsonResults.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user