arrays - Swift:数组映射或减少,用索引枚举

标签 arrays swift filter mapping reduce

我有一个值数组 [CGFloat] 和天数数组 [CGFloat],每个值都与之相关联(时间也很重要,因此天数数组是十进制值)。

每天都有 0 到 n 个值。 (n 通常小于 5 或​​ 6)

我想找到每一天的平均值,所以在计算之后我想要一个均值数组 [CGFloat] 和一个天数数组 [CGFloat],或者两者组合的字典或一个数组[CG点]。我相当确定这可以通过映射或减少或过滤功能来完成,但我在这样做时遇到了麻烦。 例如

第三天可能看起来像 [2.45, 2.75, 2.9] 具有关联值 [145.0, 150.0, 160.0]

我想以 day[2] = 2.7 结束 值[2] = 151.7

[CGPoint(2.7, 151.7)] or [2.7 : 151.7]

谁能提供指导?

部分代码:

let xValues : [CGFloat] = dates.map{round((CGFloat($0.timeIntervalSinceDate(dateZero))/(60*60*24))*100)/100}
let yValues : [CGFloat] = valueDoubles.map{CGFloat($0)}
//xValues and yValues are the same length
var dailyMeans = [CGFloat]()
var xVals = [CGFloat]()

let index = Int(ceil(xValues.last!))

for i in 0..<index{

    let thisDay = xValues.enumerate().filter{$0.element >= CGFloat(i) && $0.element < CGFloat(i+1)}
    if thisDay.count > 0{
        var sum : CGFloat = 0
        var day : CGFloat = 0
        for i in thisDay{
            sum += yValues[i.index]
            day += xValues[i.index]
        }
        dailyMeans.append(sum/CGFloat(thisDay.count))
        xVals.append(day/CGFloat(thisDay.count))
    }

}

以上代码有效,但还必须执行 enumerate.filter 函数 values.count * days.last 次。所以 40 天和 160 个读数.. 大约 6500 次。而且我已经使用了太多的处理能力。有一个更好的方法吗?

编辑:忘记了一行代码将索引定义为 xValues.last 的上限

这已被看到 1000 次,所以我想我会更新我的最终解决方案:

var daySets = [Int: [CGPoint]]()
// points is the full array of (x: dayTimeInDecimal, y: value)
for i in points {
    let day = Int(i.x)

    daySets[day] = (daySets[day] ?? []) + [i]
}

let meanPointsEachDay = daySets.map{ (key, value) -> CGPoint in
    let count = CGFloat(value.count)
    let sumPoint = value.reduce(CGPoint.zero, {CGPoint(x: $0.x + $1.x, y: $0.y + $1.y)})
    return CGPoint(x: sumPoint.x/count, y: sumPoint.y/count)
}

最佳答案

// must be sorted by 'day'!!!
let arrA0 = [2.45, 2.75, 2.9, 3.1, 3.2, 3.3]
// associated values
let arrA1 = [145.0, 150.0, 160.0, 245.0, 250.0, 260.0]

let arr = Array(zip(arrA0, arrA1))

// now i have an array of tuples, where tuple.0 is key and tuple.1 etc. is associated value
// you can expand the tuple for as much associated values, as you want
print(arr)
// [(2.45, 145.0), (2.75, 150.0), (2.9, 160.0), (3.1, 245.0), (3.2, 250.0), (3.3, 260.0)]




// now i can perform my 'calculations' the most effective way
var res:[Int:(Double,Double)] = [:]
// sorted set of Int 'day' values
let set = Set(arr.map {Int($0.0)}).sort()
// for two int values the sort is redundant, but
// don't be depend on that!

print(set)
// [2, 3]
var g = 0
var j = 0
set.forEach { (i) -> () in
    var sum1 = 0.0
    var sum2 = 0.0
    var t = true
    while t && g < arr.count {
        let v1 = arr[g].0
        let v2 = arr[g].1
        t = i == Int(v1)
        if t {
            g++
            j++
        } else {
            break
        }
        sum1 += v1
        sum2 += v2
    }
    res[i] = (sum1 / Double(j), sum2 / Double(j))
    j = 0
}
print(res)
// [2: (2.7, 151.666666666667), 3: (3.2, 251.666666666667)]

请注意,数据的每个元素在“计算”中仅处理一次,与“键”集大小的大小无关

使用 Swift 的 Double 而不是 CGFloat!这也提高了速度:-)

最后是你要找的东西

if let (day, value) = res[2] {
    print(day, value) // 2.7 151.666666666667
}

关于arrays - Swift:数组映射或减少,用索引枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34842391/

相关文章:

php - 警告 : mysqli_fetch_array() expects parameter 1 to be mysqli_result when I have 2 parameters

arrays - 从两个 slice 的重复项创建一个 slice

javascript - 获取选定/突出显示的 DIV 的所有 ID

swift - iOS 13 之前的场景委托(delegate)如何使用?

Java 8 按属性过滤

arrays - 如何在 Perl 中将一个数组分成两个不同的数组

json - 如何在表格 View 中创建通知徽章

swift - 'SKView ?' does not have a member named ' 界限'

python - 按行过滤数据框

PHP:文件到数组检查和替换