Swift - 按值对数组元素进行分组(2 x 2、3 x 3 等...)
Swift - Group elements of Array by value (2 by 2, 3 by 3, etc...)
编辑:我不是在要求一个函数来计算发生的次数。我要求一个函数来计算 2 乘以 2、3 乘以 3、10 乘以 10,等等...这是我的问题
我有一组分数,比方说:
[2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
我想要一个函数将此 Array
转换为 Dictionary [Int: Int]()
以实现类似的功能:
func groupArrayBy(array: Array<Int>, coef: Int) -> Array<Int, Int>{
// if coef = 2 -> 2 by 2, count occurence
// Transform the array to:
// [2: 3, 4: 5, 6: 2, 8: 4, 10: 2]
// return Dictionary
}
(coef = 3,它将是:[2: 7, 5: 3, 8: 6]
-> 3 x 3)
我对此一无所知。有可能吗?
你的问题太令人困惑了 coef
是什么意思,或者我们可以期望输入数组是排序的,你想要什么输出类型。 Swift 中没有 Array<Int, Int>
。
假设输入数组已经排序并且你想要Array<(Int, Int)>
,你可以这样写:
func getRanges(_ arr: [Int], _ step: Int) -> [Range<Int>] {
return stride(from: arr.first!, through: arr.last!, by: step)
.map {[=10=]..<[=10=]+step}
}
func groupArrayBy(array: Array<Int>, coef: Int) -> [(Int, Int)] {
let grpArr = getRanges(arr, coef).map {rng in
(rng.lowerBound, arr.lazy.filter{rng.contains([=10=])}.count)
}
return grpArr
}
print(groupArrayBy(array: arr, coef: 2)) //->[(2, 3), (4, 5), (6, 2), (8, 4), (10, 2)]
print(groupArrayBy(array: arr, coef: 3)) //->[(2, 7), (5, 3), (8, 6)]
我的代码效率不高,可能有人可以向您展示更高效的代码。
我对系数还是有点困惑。但是,假设您想要的是将任何值 N
与下一个 N+coefficient
值分组。
然后我将从将原始数组重新映射到组值开始:
let items = [2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
let uniqueItems = Set(items)
var itemCoefficientMapping: [Int: Int] = [:]
let coefficient = 3
for item in uniqueItems.sorted() {
// look whether exists some lower value that is not itself mapped to another value
let normalizedItem = (item - (coefficient - 1)...item).first {
uniqueItems.contains([=10=]) && itemCoefficientMapping[[=10=]] == [=10=]
} ?? item
itemCoefficientMapping[item] = normalizedItem
}
// count by mapped value
let counts: [Int: Int] = items.reduce(into: [:]) { result, value in
result[itemCoefficientMapping[value] ?? value, default: 0] += 1
}
print(counts)
这是我的版本,我根据数组的第一个值和 coef
变量过滤范围,根据结果我切掉那些已经计算过的元素并再次过滤较小的数组一个循环。此解决方案要求输入数组按升序排序
func group(_ array: [Int], coef: Int) -> [Int: Int] {
var result:[Int:Int] = [:]
var start = array[0]
var end = start + coef - 1
var arr = array
while start <= array[array.count - 1] {
let count = arr.filter({ [=10=] >= start && [=10=] <= end}).count
result[start] = count
start = end + 1
end = start + coef - 1
arr = Array(arr[count...])
}
return result
}
这里是上述函数的递归版本
func group(_ array: [Int], coef: Int) -> [Int: Int] {
var result:[Int:Int] = [:]
if array.isEmpty { return result }
let end = array[0] + coef - 1
let count = array.filter({ [=11=] >= array[0] && [=11=] <= end}).count
result[array[0]] = count
result = result.merging(group(Array(array[count...]), coef: coef)) { }
return result
}
它可能还有一个更简单的代码:
let aa : [Int] = [2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
let mini = aa.min()!
let coeff : Int = 3
let dict = Dictionary(grouping: aa) {
mini + (([=10=] - mini) / coeff) * coeff
}.mapValues{[=10=].count}
print (dict)
编辑:我不是在要求一个函数来计算发生的次数。我要求一个函数来计算 2 乘以 2、3 乘以 3、10 乘以 10,等等...这是我的问题
我有一组分数,比方说:
[2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
我想要一个函数将此 Array
转换为 Dictionary [Int: Int]()
以实现类似的功能:
func groupArrayBy(array: Array<Int>, coef: Int) -> Array<Int, Int>{
// if coef = 2 -> 2 by 2, count occurence
// Transform the array to:
// [2: 3, 4: 5, 6: 2, 8: 4, 10: 2]
// return Dictionary
}
(coef = 3,它将是:[2: 7, 5: 3, 8: 6]
-> 3 x 3)
我对此一无所知。有可能吗?
你的问题太令人困惑了 coef
是什么意思,或者我们可以期望输入数组是排序的,你想要什么输出类型。 Swift 中没有 Array<Int, Int>
。
假设输入数组已经排序并且你想要Array<(Int, Int)>
,你可以这样写:
func getRanges(_ arr: [Int], _ step: Int) -> [Range<Int>] {
return stride(from: arr.first!, through: arr.last!, by: step)
.map {[=10=]..<[=10=]+step}
}
func groupArrayBy(array: Array<Int>, coef: Int) -> [(Int, Int)] {
let grpArr = getRanges(arr, coef).map {rng in
(rng.lowerBound, arr.lazy.filter{rng.contains([=10=])}.count)
}
return grpArr
}
print(groupArrayBy(array: arr, coef: 2)) //->[(2, 3), (4, 5), (6, 2), (8, 4), (10, 2)]
print(groupArrayBy(array: arr, coef: 3)) //->[(2, 7), (5, 3), (8, 6)]
我的代码效率不高,可能有人可以向您展示更高效的代码。
我对系数还是有点困惑。但是,假设您想要的是将任何值 N
与下一个 N+coefficient
值分组。
然后我将从将原始数组重新映射到组值开始:
let items = [2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
let uniqueItems = Set(items)
var itemCoefficientMapping: [Int: Int] = [:]
let coefficient = 3
for item in uniqueItems.sorted() {
// look whether exists some lower value that is not itself mapped to another value
let normalizedItem = (item - (coefficient - 1)...item).first {
uniqueItems.contains([=10=]) && itemCoefficientMapping[[=10=]] == [=10=]
} ?? item
itemCoefficientMapping[item] = normalizedItem
}
// count by mapped value
let counts: [Int: Int] = items.reduce(into: [:]) { result, value in
result[itemCoefficientMapping[value] ?? value, default: 0] += 1
}
print(counts)
这是我的版本,我根据数组的第一个值和 coef
变量过滤范围,根据结果我切掉那些已经计算过的元素并再次过滤较小的数组一个循环。此解决方案要求输入数组按升序排序
func group(_ array: [Int], coef: Int) -> [Int: Int] {
var result:[Int:Int] = [:]
var start = array[0]
var end = start + coef - 1
var arr = array
while start <= array[array.count - 1] {
let count = arr.filter({ [=10=] >= start && [=10=] <= end}).count
result[start] = count
start = end + 1
end = start + coef - 1
arr = Array(arr[count...])
}
return result
}
这里是上述函数的递归版本
func group(_ array: [Int], coef: Int) -> [Int: Int] {
var result:[Int:Int] = [:]
if array.isEmpty { return result }
let end = array[0] + coef - 1
let count = array.filter({ [=11=] >= array[0] && [=11=] <= end}).count
result[array[0]] = count
result = result.merging(group(Array(array[count...]), coef: coef)) { }
return result
}
它可能还有一个更简单的代码:
let aa : [Int] = [2,2,3,4,4,4,4,5,6,6,8,8,8,9,10,10]
let mini = aa.min()!
let coeff : Int = 3
let dict = Dictionary(grouping: aa) {
mini + (([=10=] - mini) / coeff) * coeff
}.mapValues{[=10=].count}
print (dict)