How can sum the elements in array in kotlin language? - arrays

package sum
fun sum(a: IntArray): Int {
return 0
}

There's a built in function to sum an IntArray in Kotlin
val numbers: IntArray = intArrayOf(10, 20, 30, 40, 50)
val sum = numbers.sum()
Or to do it yourself...
fun sumArray(array: IntArray): Int{
var sum = 0
for(number in array){
sum += number
}
return sum
}

You can use sum directly:
val sum = arrayOf(12, 33).sum()

You could do it as a stream
val sum = arrayOf(7, 9).fold(0) { acc, e -> acc + e }

fun sum(numbers: IntArray) = numbers.sum()

This is the solution I prefer
array.reduce { acc, l -> acc + l }
If you've got an object instead of a primary data for example, you can access it and sumup

You can also use fold. The advantage is more freedom with data handling.
For example, if you have nested arrays, and want the sum of the nested array sizes, you can do something like this:
val totalSize = array1.fold(0) { acc, i -> acc + i.array2.size }
In case of array with just integers:
val sum = array.fold(0) { acc, i -> acc + i }

Related

Concurrent access to elements of Array in Swift

I try to write and read from Arrays (from different arrays) in Swift in concurrent way, and have exception in the runtime on write operation.
I have concurrent blur code in Objective-C++:
- (cpp_blur::Bitmap)blur {
Bitmap result(_source);
auto indexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _source.size())];
int minIndex = 0;
int maxIndex = static_cast<int>(result.size()) - 1;
[indexes enumerateIndexesWithOptions:NSEnumerationConcurrent
usingBlock:[&](NSUInteger idx, BOOL* _Nonnull stop){
double sum = 0.0;
for (int i = static_cast<int>(idx) - static_cast<int>(self.radius); i <= idx + self.radius; i++) {
int index = clamp(i, minIndex, maxIndex);
sum += self->_source.at(index);
}
sum /= static_cast<double>(self.radius * 2 + 1);
result.at(idx) = sum;
}];
return result;
}
I try to write same code in Swift:
#objc public func blur() -> [Double] {
var result = source
let indexSet = NSIndexSet(indexesIn: NSMakeRange(0, source.count))
let from = -Int(self.blurRadius)
let to = Int(self.blurRadius)
let lastIndex = self.source.count - 1
indexSet.enumerate(options: .concurrent) { (index:Int, _) in
let sum = ((from + index)...(to + index)).reduce(0.0) { (partial:Double, nonClamped:Int) -> Double in
let index = self.clamp(nonClamped, min: 0, max: lastIndex)
let result = partial + self.source[index]
return result
}
let avg = sum / Double(2 * self.blurRadius + 1);
result[index] = avg //here I have crash in runtime
}
return result
}
If I add a lock around result[index] = avg, this exception will move away, but I will have performance issue.
How I can change values of elements in Swift Array without lock (In same time I change only different elements)?
Github repo.

Index out of range: Mapping the output of a 3-input function to a 3-dimentional floating-point array in Swift 4

I want to set the elements in a mutable 3d array of Doubles to the output of a 3-input function, f(), for the position of that element in the array ([a][n][b]), then print the array.
//3-input function must input and output doubles. This function is an example.
func f(a: Double, n: Double, b: Double) -> Double {
return a * n * b
}
//Size of array: 7*7*7
let aMax = 6
let nMax = 6
let bMax = 6
//Define mutable array; I don't know if I need to initialize array "points".
var points = [[[Double]]]()
//I don't know if I should use ".append" or "=".
for a in 0...aMax {
for n in 0...nMax {
for b in 0...bMax {
points[a][n][b] = f(a: Double(a), n: Double(n), b: Double(b)) //Changing element at position results in "fatal error: Index out of range".
}
}
}
print(points)
The problem is that after doing:
var points = [[[Double]]]()
points is completely empty. So any attempt to access any of the indexes results in the "Index out of range" error.
Since you are going to fill the whole thing, initializing the three dimensions using Array(repeating:count:).
var points = Array(repeating: Array(repeating: Array(repeating: 0.0, count: bMax + 1), count: nMax + 1), count: aMax + 1)
Now the rest of your code will work.
You can try this , for an array declared like this [[[Double]]] you can use append only but for assigning and indexing it you must first init it like this
//Size of array: 7*7*7
let aMax = 7
let nMax = 7
let bMax = 7
//Define mutable array; I don't know if I need to initialize array "points".
var points = [[[Double]]](repeating: [[Double]](repeating: [Double](repeating: 0, count: bMax), count: nMax), count: aMax)
//I don't know if I should use ".append" or "=".
for a in 0..<aMax {
for n in 0..<nMax {
for b in 0..<bMax {
points[a][n][b] = (f(a: Double(a), n: Double(n), b: Double(b))) //Changing element at position results in "fatal error: Index out of range".
}
}
}
print(points)
You can declare and initialize a "3D" array in a single shot, using Array.map(_:):
let (aCount, nCount, bCount) = (8, 8, 8)
let points: [[[Double]]] = (0 ..< aCount).map { aInt in
let a = Double(aInt)
return (0 ..< nCount).map { nInt in
let n = Double(nInt)
return (0 ..< bCount).map { bInt in
return f(a: a, n: n, b: Double(bInt))
}
}
}

Get median of array

I have an array that looks like this:
let arr = [1,2,3,4,5,6,7,8,9]
I know you can get min and max by:
let min = arr.min()
let max = arr.max()
But how do you get the median?
To get the median you can use the following:
let median = arr.sorted(by: <)[arr.count / 2]
In your case it will return 5.
As #Nirav pointed out [1,2,3,4,5,6,7,8] will return 5 but should return 4.5.
Use this instead:
func calculateMedian(array: [Int]) -> Float {
let sorted = array.sorted()
if sorted.count % 2 == 0 {
return Float((sorted[(sorted.count / 2)] + sorted[(sorted.count / 2) - 1])) / 2
} else {
return Float(sorted[(sorted.count - 1) / 2])
}
}
Usage:
let array = [1,2,3,4,5,6,7,8]
let m2 = calculateMedian(array: array) // 4.5
The median is defined as the number in the middle of the sequence. If there is not one middle number, then it's the average of the two middle numbers.
extension Array where Element == Int {
func median() -> Double {
let sortedArray = sorted()
if count % 2 != 0 {
return Double(sortedArray[count / 2])
} else {
return Double(sortedArray[count / 2] + sortedArray[count / 2 - 1]) / 2.0
}
}
}
Note that if the array is empty, the median is undefined. So a safe median function returns an optional, just like the min() and max() built-in methods do.
extension Array where Element == Int {
func median() -> Double? {
guard count > 0 else { return nil }
let sortedArray = self.sorted()
if count % 2 != 0 {
return Double(sortedArray[count/2])
} else {
return Double(sortedArray[count/2] + sortedArray[count/2 - 1]) / 2.0
}
}
}
With that defined, you can write:
if let median = arr.median() {
// do something
}
If someone (like me) likes two*-liners:
let sorted = arr.sorted(by: <)
let median = Double(sorted[arr.count/2] + sorted.reversed()[arr.count/2])/2.0
Algorithms that use sorted take O(n log n) time. That's typically not a problem for 9 numbers, but if your array is large, use an algorithm that completes in O(n) time. An example is this k-th largest element algorithm. It recursively partitions the array, but doesn’t have to go through all the work to sort it, so it’s much faster.

Sort Array and a Corresponding Array [duplicate]

This question already has answers here:
How can I sort multiple arrays based on the sorted order of another array
(2 answers)
Closed 6 years ago.
Say I have and array [4, 1, 8, 5] and another array that corresponds to each object in the first array, say ["Four", "One", "Eight", "Five"]. How can I sort the first array in ascending order while also moving the corresponding object in the second array to the same index in Swift?
Doesn't sound like best practice but this will solve your problem:
var numbers = [4,7,8,3]
var numbersString = ["Four","Seven","Eight","Three"]
func bubbleSort<T,Y>(inout numbers:[T],inout _ mirrorArray: [Y], _ comapre : (T,T)->(Bool)) -> () {
let numbersLength = numbers.count
for i in 0 ..< numbersLength {
for j in 1 ..< numbersLength-i {
if comapre(numbers[j-1],numbers[j]) {
swap(&numbers[j-1], &numbers[j])
swap(&mirrorArray[j-1], &mirrorArray[j])
}
}
}
}
bubbleSort(&numbers,&numbersString) { (a, b) -> (Bool) in
a<b
}
print(numbers,numbersString)
*This is generic therefore will work with any type and let you supply the condition
Using quick sort:
func quicksort_swift(inout a:[Int], inout b:[String], start:Int, end:Int) {
if (end - start < 2){
return
}
let p = a[start + (end - start)/2]
var l = start
var r = end - 1
while (l <= r){
if (a[l] < p){
l += 1
continue
}
if (a[r] > p){
r -= 1
continue
}
let t = a[l]
let t1 = b[l]
a[l] = a[r]
b[l] = b[r]
a[r] = t
b[r] = t1
l += 1
r -= 1
}
quicksort_swift(&a, b: &b, start: start, end: r + 1)
quicksort_swift(&a, b: &b, start: r + 1, end: end)
}
Although, the dictionary solution offered by #NSNoob, should be faster and more elegant.

Finding sum of elements in Swift array

What is the easiest (best) way to find the sum of an array of integers in swift?
I have an array called multiples and I would like to know the sum of the multiples.
This is the easiest/shortest method I can find.
Swift 3 and Swift 4:
let multiples = [...]
let sum = multiples.reduce(0, +)
print("Sum of Array is : ", sum)
Swift 2:
let multiples = [...]
sum = multiples.reduce(0, combine: +)
Some more info:
This uses Array's reduce method (documentation here), which allows you to "reduce a collection of elements down to a single value by recursively applying the provided closure". We give it 0 as the initial value, and then, essentially, the closure { $0 + $1 }. Of course, we can simplify that to a single plus sign, because that's how Swift rolls.
Swift 3+ one liner to sum properties of objects
var totalSum = scaleData.map({$0.points}).reduce(0, +)
Where points is the property in my custom object scaleData that I am trying to reduce
In Swift 4 You can also constrain the sequence elements to Numeric protocol to return the sum of all elements in the sequence as follow
extension Sequence where Element: Numeric {
/// Returns the sum of all elements in the collection
func sum() -> Element { return reduce(0, +) }
}
edit/update:
Xcode 10.2 • Swift 5 or later
We can simply constrain the sequence elements to the new AdditiveArithmetic protocol to return the sum of all elements in the collection
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element {
return reduce(.zero, +)
}
}
Xcode 11 • Swift 5.1 or later
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element { reduce(.zero, +) }
}
let numbers = [1,2,3]
numbers.sum() // 6
let doubles = [1.5, 2.7, 3.0]
doubles.sum() // 7.2
To sum a property of a custom object we can extend Sequence to take a predicate to return a value that conforms to AdditiveArithmetic:
extension Sequence {
func sum<T: AdditiveArithmetic>(_ predicate: (Element) -> T) -> T { reduce(.zero) { $0 + predicate($1) } }
}
Usage:
struct Product {
let id: String
let price: Decimal
}
let products: [Product] = [.init(id: "abc", price: 21.9),
.init(id: "xyz", price: 19.7),
.init(id: "jkl", price: 2.9)
]
products.sum(\.price) // 44.5
Swift3 has changed to :
let multiples = [...]
sum = multiples.reduce(0, +)
Swift 4 example
class Employee {
var salary: Int = 0
init (_ salary: Int){
self.salary = salary
}
}
let employees = [Employee(100),Employee(300),Employee(600)]
var sumSalary = employees.reduce(0, {$0 + $1.salary}) //1000
This also works:
let arr = [1,2,3,4,5,6,7,8,9,10]
var sumedArr = arr.reduce(0, combine: {$0 + $1})
print(sumedArr)
The result will be: 55
Swift 3
If you have an array of generic objects and you want to sum some object property then:
class A: NSObject {
var value = 0
init(value: Int) {
self.value = value
}
}
let array = [A(value: 2), A(value: 4)]
let sum = array.reduce(0, { $0 + $1.value })
// ^ ^
// $0=result $1=next A object
print(sum) // 6
Despite of the shorter form, many times you may prefer the classic for-cycle:
let array = [A(value: 2), A(value: 4)]
var sum = 0
array.forEach({ sum += $0.value})
// or
for element in array {
sum += element.value
}
Swift 3, 4, and 5
Using reduce:
let totalAmount = yourTransactionsModelArray.reduce(0) { $0 + $1.amount}
Old fashioned way for understanding purposes:
for (var i = 0; i < n; i++) {
sum = sum + Int(multiples[i])!
}
//where n = number of elements in the array
A possible solution: define a prefix operator for it.
Like the reduce "+/" operator as in APL (e.g. GNU APL)
A bit of a different approach here.
Using a protocol en generic type allows us to to use this operator on Double, Float and Int array types
protocol Number
{
func +(l: Self, r: Self) -> Self
func -(l: Self, r: Self) -> Self
func >(l: Self, r: Self) -> Bool
func <(l: Self, r: Self) -> Bool
}
extension Double : Number {}
extension Float : Number {}
extension Int : Number {}
infix operator += {}
func += <T:Number> (inout left: T, right: T)
{
left = left + right
}
prefix operator +/ {}
prefix func +/ <T:Number>(ar:[T]?) -> T?
{
switch true
{
case ar == nil:
return nil
case ar!.isEmpty:
return nil
default:
var result = ar![0]
for n in 1..<ar!.count
{
result += ar![n]
}
return result
}
}
use like so:
let nmbrs = [ 12.4, 35.6, 456.65, 43.45 ]
let intarr = [1, 34, 23, 54, 56, -67, 0, 44]
+/nmbrs // 548.1
+/intarr // 145
(updated for Swift 2.2, tested in Xcode Version 7.3)
Swift 3.0
i had the same problem, i found on the documentation Apple this solution.
let numbers = [1, 2, 3, 4]
let addTwo: (Int, Int) -> Int = { x, y in x + y }
let numberSum = numbers.reduce(0, addTwo)
// 'numberSum' == 10
But, in my case i had a list of object, then i needed transform my value of my list:
let numberSum = self.list.map({$0.number_here}).reduce(0, { x, y in x + y })
this work for me.
another easy way of getting it done:
let sumOfMultiples = ar.reduce(0) { x, y in x + y }
print(sumOfMultiples)
Keep it simple...
var array = [1, 2, 3, 4, 5, 6, 7, 9, 0]
var n = 0
for i in array {
n += i
}
print("My sum of elements is: \(n)")
Output:
My sum of elements is: 37
For me, it was like this using property
let blueKills = match.blueTeam.participants.reduce(0, { (result, participant) -> Int in
result + participant.kills
})
#IBOutlet var valueSource: [MultipleIntBoundSource]!
private var allFieldsCount: Int {
var sum = 0
valueSource.forEach { sum += $0.count }
return sum
}
used this one for nested parameters
For sum of elements in array of Objects
self.rankDataModelArray.flatMap{$0.count}.reduce(0, +)

Resources