我真的需要你的帮助。我有一组看起来像这样的元组:
[("07-21-2016", 5), ("07-21-2016", 1), ("07-21-2016", 2), ("07-21-2016", 3), ("07-21-2016", 4), ("07-21-2016", 5), ("07-20-2016", 6), ("07-20-2016", 5), ("07-19-2016", 5)]
我需要使用相同日期的所有元组并将它们平均化。所以最后它看起来像:
[("07-21-2016", 33.3), ("07-20-2016", 5.5), ("07-19-2016", 5)]
有谁知道怎么做?
答案 0 :(得分:2)
let array = [("07-21-2016", 5), ("07-21-2016", 1), ("07-21-2016", 2), ("07-21-2016", 3), ("07-21-2016", 4), ("07-21-2016", 5), ("07-20-2016", 6), ("07-20-2016", 5), ("07-19-2016", 5)]
// Create dictionary to hold mapping of date to array of values
var dict = [String: [Double]]()
// use forEach to add each value to the array for each key
array.forEach {(date, num) in dict[date] = (dict[date] ?? []) + [Double(num)]}
// use map with reduce to find the average of each value and return a tuple
// containing the date and the average value
let result = dict.map {(date, nums) in (date, nums.reduce(0, combine: +) / Double(nums.count))}
print(result)
输出:
[("07-20-2016", 5.5), ("07-19-2016", 5.0), ("07-21-2016", 3.3333333333333335)]
array.forEach {(date, num) in dict[date] = (dict[date] ?? []) + [Double(num)]}
forEach
获取数组的每个元组,查找与dict[date]
对应的值数组,并将新的num
附加到该数组。如果dict[date]
返回nil
,那么这是我们第一次看到此密钥,因此请使用 nil coalescing operator ??
返回一个空数组[]
并将新值附加到该数据。
最后,dict
的内容是:
["07-20-2016": [6.0, 5.0], "07-19-2016": [5.0], "07-21-2016": [5.0, 1.0, 2.0, 3.0, 4.0, 5.0]]
let result = dict.map {(date, nums) in (date, nums.reduce(0, combine: +) / Double(nums.count))}
当map
应用于字典时,它会占用每个(key, value)
对,并根据该值创建新值。 map
的最终结果是它返回的值的新数组。在这种情况下,每次map
次迭代返回的值是一个包含date
的元组以及与该日期相关的数字的平均值。
nums.reduce(0, combine: +)
这会对nums数组中的值求和。 reduce
采用初始值(在这种情况下为0
)和将为nums
数组中的每个值计算的闭包。 reduce
的每次迭代都会获取当前运行总计和nums
中的下一个值并对它们求和。然后将该总和除以Double(nums.count)
以产生平均值。最后,map
返回(date, avg)
,产生最终结果。
答案 1 :(得分:0)
这是一种方式(使用字典整理数字):
let dateValues = [("07-21-2016", 5), ("07-21-2016", 1), ("07-21-2016", 2), ("07-21-2016", 3), ("07-21-2016", 4), ("07-21-2016", 5), ("07-20-2016", 6), ("07-20-2016", 5), ("07-19-2016", 5)]
var averages:[String:(Int,Int)] = [:]
for (date,value) in dateValues
{
averages[date] = averages[date] ?? (0,0)
averages[date] = (averages[date]!.0 + value, averages[date]!.1 + 1)
}
let averagePerDate = averages.map{($0,Float($1.0)/Float($1.1))}.sort{$0.0>$1.0}
print(averagePerDate)
// [("07-21-2016", 3.33333325), ("07-20-2016", 5.5), ("07-19-2016", 5.0)]
使用集合更简洁:
let dateList = dateValues.reduce( Set<String>(), combine: { $0.union(Set([$1.0])) })
let dateData = dateList.map{ date in return (date, dateValues.filter({$0.0==date}).map{$0.1}) }
let dateCounts = dateData.map{ ($0, $1.reduce(0,combine:+), Float($1.count) ) }
let dateAverages = dateCounts.map{ ($0, Float($1/$2) ) }.sort{$0.0>$1.0}
print(dateAverages)