How to turn an array of an array of doubles into string, Swift - arrays

I have an array of array of doubles. How do you convert that to a single string printed on the console?
I need to create a function that takes in an array of arrays of doubles as a parameter and returns a string object. Then loop through each of the inner arrays and concatenate each element of the inner arrays into a String object. But I'm not sure how to go about that.
var array1 = [2.6, 6.7, 7.2, 4.1, 3.1]
var array2 = [1.2, 3.5, 2.8, 4.5, 6.4]
var array3 = [1.2, 1.3, 1.4, 1.5, 1.6]
var nestedArray = [array1, array2, array3]
This is the code I have... but i don't know how to do a for loop that would give me my answer...
func nestedFunction(nestedArray: [[Double]]) -> String {
var stringVar: String = ""
( for loop here... )
return stringVar
}
print(nestedArrayFunction(nestedArray))
The expected output should be a string object, with no brackets

If you want it without the brackets:
let string = nestedArray.flatMap { (array) in
array.flatMap { String($0) }.joinWithSeparator(",")
}.joinWithSeparator(",")
Output:
"2.6,6.7,7.2,4.1,3.1,1.2,3.5,2.8,4.5,6.4,1.2,1.3,1.4,1.5,1.6"
Mind that using , as separator isn't localisation proof, and in French locale would result in a string like "2,6,6,7,7,2" and so on.

From the description in your question it seems as if the argument of nestedFunction(...) should be an array of arrays with double valued elements ([[Double]]) rather than an array with double valued elements ([Double]).
You can make use of .flatten() to your simply nested array nestedArray in nestedFunction(...), and thereafter e.g. reduce to transform the Double valued elements of the flattened array to one concenated String.
var array1 = [2.6, 6.7, 7.2, 4.1, 3.1]
var array2 = [1.2, 3.5, 2.8, 4.5, 6.4]
var array3 = [1.2, 1.3, 1.4, 1.5, 1.6]
var nestedArray = [array1, array2, array3]
func nestedFunction (nestedArray: [[Double]])-> String {
return String(nestedArray
.flatten()
.reduce("") { $0 + ", " + String($1) }
.characters.dropFirst(2))
}
let asString = nestedFunction(nestedArray)
// asString = "2.6, 6.7, 7.2, 4.1, 3.1, 1.2, 3.5, 2.8, 4.5, 6.4, 1.2, 1.3, 1.4, 1.5, 1.6"
As an alternative, if you're set on using a for loop, you can use for ... in on the flattened array, e.g.:
var array1 = [2.6, 6.7, 7.2, 4.1, 3.1]
var array2 = [1.2, 3.5, 2.8, 4.5, 6.4]
var array3 = [1.2, 1.3, 1.4, 1.5, 1.6]
var nestedArray = [array1, array2, array3]
func nestedFunction (nestedArray: [[Double]])-> String {
var stringVar: String = ""
var isFirstElement = true
for elem in nestedArray.flatten() {
stringVar += (isFirstElement ? "" : ", ") + String(elem)
isFirstElement = false
}
return stringVar
}
let asString = nestedFunction(nestedArray)
// asString = "2.6, 6.7, 7.2, 4.1, 3.1, 1.2, 3.5, 2.8, 4.5, 6.4, 1.2, 1.3, 1.4, 1.5, 1.6"
Note that due to limited floating point precision, some double values might end up with a "messy" String representation (e.g. 2.6 might end up as 2.6000000000000001) when using the direct String initializer (String($1) and String(elem) above, in the first and second method, respectively). To redeem this you could set a fixed number of fraction digits for the String representation of your Double values, using the following String initializer:
String(format: "%.3f", myDoubleValue)
/* \
number of fraction digits (3 here) */
E.g., replace String($1) and String(elem) in the methods above by String(format: "%.3f", $1) and String(format: "%.3f", elem), respectively, for some number of fraction digits of your choice. The Double values will be rounded to the number of supplied fraction digits.

Array conforms to CustomStringConvertible, so you can just use its description property:
nestedArray.description
output:
[[2.6000000000000001, 6.7000000000000002, 7.2000000000000002, 4.0999999999999996, 3.1000000000000001], [1.2, 3.5, 2.7999999999999998, 4.5, 6.4000000000000004], [1.2, 1.3, 1.3999999999999999, 1.5, 1.6000000000000001]]
This is what the regular print function uses to print such arrays.

First, you will need to concatenate, or combine, the arrays you have. You can do that simply by creating another array, like this;
let fullArray = array1 + array2 + array3
Next, you can print the full array,
print(fullArray)
Which would give you something like
[2.6000000000000001, 6.7000000000000002, 7.2000000000000002, 4.0999999999999996, 3.1000000000000001, 1.2, 3.5, 2.7999999999999998, 4.5, 6.4000000000000004]
or you can create a string representation of this array using the .joinWithSeparator(String: String) method, like so
let stringRepresentation = fullArray.joinWithSeparator(",")
print(stringRepresentation)
Hope this helps!

Related

Sum of the previous elements in an array [duplicate]

This question already has answers here:
How can I sum array elements in place in ruby?
(5 answers)
Closed 5 years ago.
I have a array
[3.0, 3.0, 2.0, 5.0, 6.0, 10.0]
For each element of the array, I need the sum of its previous elements.
I know how get the previous element but not all the previous elements.
last = mytab[index - 1] //change here
res = (e + last) / (index + 1)
You can iterate with each_with_object
numbers = [3.0, 3.0, 2.0, 5.0, 6.0, 10.0]
sum_of_repvious = numbers.each_with_object([]) do |number, accu|
previous = accu.last || 0 # on the first iteration, there is no previous, initialize to 0
accu << previous += number
end
p sum_of_repvious #> [3.0, 6.0, 8.0, 13.0, 19.0, 29.0]
Let me explain a bit more in detail what is going on here:
With each_with_object you iterate the array and have an additional object that is passed to each iteration. I chose it to be an empty array (the []).
I call this accumlator or accu for short.
In this array i store the sum of the previous numbers. On the first step, there is no previous sum, hence the || 0 to make sure that we have 0 instead of nil.
Now you have an array that has the sum of the numbers in your original array up to the respective index.
def sum_array_of_last_elements(array)
array.reduce([]) { |memo, itm| memo << itm.to_f + memo.last.to_f }
end
for Simple and easy way try Array#map
> sum = 0
> a.map{|x| sum += x}
#=> [3.0, 6.0, 8.0, 13.0, 19.0, 29.0]
Note: As per experts this is not good practice, just alternate solution

Create array with non-integer increments

I am trying to create time stamp arrays in Swift.
So, say I want to go from 0 to 4 seconds, I can use Array(0...4), which gives [0, 1, 2, 3, 4]
But how can I get [0.0, 0.5 1.0, 2.0, 2.5, 3.0, 3.5, 4.0]?
Essentially I want a flexible delta, such as 0.5, 0.05, etc.
You can use stride(from:through:by:):
let a = Array(stride(from: 0.0, through: 4.0, by: 0.5))
An alternative for non-constant increments (even more viable in Swift 3.1)
The stride(from:through:by:) functions as covered in #Alexander's answer is the fit for purpose solution where, but for the case where readers of this Q&A wants to construct a sequence (/collection) of non-constant increments (in which case the linear-sequence constructing stride(...) falls short), I'll also include another alternative.
For such scenarios, the sequence(first:next:) is a good method of choice; used to construct a lazy sequence that can be repeatedly queried for the next element.
E.g., constructing the first 5 ticks for a log10 scale (Double array)
let log10Seq = sequence(first: 1.0, next: { 10*$0 })
let arr = Array(log10Seq.prefix(5)) // [1.0, 10.0, 100.0, 1000.0, 10000.0]
Swift 3.1 is intended to be released in the spring of 2017, and with this (among lots of other things) comes the implementation of the following accepted Swift evolution proposal:
SE-0045: Add prefix(while:) and drop(while:) to the stdlib
prefix(while:) in combination with sequence(first:next) provides a neat tool for generating sequences with everything for simple next methods (such as imitating the simple behaviour of stride(...)) to more advanced ones. The stride(...) example of this question is a good minimal (very simple) example of such usage:
/* this we can do already in Swift 3.0 */
let delta = 0.05
let seq = sequence(first: 0.0, next: { $0 + delta})
/* 'prefix(while:)' soon available in Swift 3.1 */
let arr = Array(seq.prefix(while: { $0 <= 4.0 }))
// [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
// ...
for elem in sequence(first: 0.0, next: { $0 + delta})
.prefix(while: { $0 <= 4.0 }) {
// ...
}
Again, not in contest with stride(...) in the simple case of this Q, but very viable as soon as the useful but simple applications of stride(...) falls short, e.g. for a constructing non-linear sequences.

In Swift how can I sort one array based on another array?

In Swift, say I have two arrays:
var array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
var array2: [Int] = [1, 0, 2, 0, 3]
Now, I want to sort array1 in ascending order and reindex array2 accordingly so that I get
array1 = [1.2, 1.5, 2.4, 10.9, 20.4]
array2 = [1, 3, 0, 0, 2]
Is there a simple way to do this using Swift functions or syntax?
I know I can build a function to do it and can keep track of indices, but I'm curious if there is a more elegant solution.
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
// use zip to combine the two arrays and sort that based on the first
let combined = zip(array1, array2).sorted {$0.0 < $1.0}
print(combined) // "[(1.2, 1), (1.5, 3), (2.4, 0), (10.9, 0), (20.0, 2)]"
// use map to extract the individual arrays
let sorted1 = combined.map {$0.0}
let sorted2 = combined.map {$0.1}
print(sorted1) // "[1.2, 1.5, 2.4, 10.9, 20.0]"
print(sorted2) // "[1, 3, 0, 0, 2]"
Sorting more than 2 arrays together
If you have 3 or more arrays to sort together, you can sort one of the arrays along with its offsets, use map to extract the offsets, and then use map to order the other arrays:
let english = ["three", "five", "four", "one", "two"]
let ints = [3, 5, 4, 1, 2]
let doubles = [3.0, 5.0, 4.0, 1.0, 2.0]
let roman = ["III", "V", "IV", "I", "II"]
// Sort english array in alphabetical order along with its offsets
// and then extract the offsets using map
let offsets = english.enumerated().sorted { $0.element < $1.element }.map { $0.offset }
// Use map on the array of ordered offsets to order the other arrays
let sorted_english = offsets.map { english[$0] }
let sorted_ints = offsets.map { ints[$0] }
let sorted_doubles = offsets.map { doubles[$0] }
let sorted_roman = offsets.map { roman[$0] }
print(sorted_english)
print(sorted_ints)
print(sorted_doubles)
print(sorted_roman)
Output:
["five", "four", "one", "three", "two"]
[5, 4, 1, 3, 2]
[5.0, 4.0, 1.0, 3.0, 2.0]
["V", "IV", "I", "III", "II"]
You could "link" the items of each array by mapping over the indices to create an array of tuples, then sort the tuples according to the first array's values before extracting the original arrays.
assert(array1.count == array2.count, "The following technique will only work if the arrays are the same length.")
let count = array1.count
// Create the array of tuples and sort according to the
// first tuple value (i.e. the first array)
let sortedTuples = (0..<count).map { (array1[$0], array2[$0]) }.sort { $0.0 < $1.0 }
// Map over the sorted tuples array to separate out the
// original (now sorted) arrays.
let sortedArray1 = sortedTuples.map { $0.0 }
let sortedArray2 = sortedTuples.map { $0.1 }
Swift 4
This part is translated from #vacawama's answer to Swift 4 syntax
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
// use zip to combine the two arrays and sort that based on the first
let combined = zip(array1, array2).sorted(by: {$0.0 < $1.0})
print(combined) // "[(1.2, 1), (1.5, 3), (2.4, 0), (10.9, 0), (20.0, 2)]"
// use map to extract the individual arrays
let sorted1 = combined.map {$0.0}
let sorted2 = combined.map {$0.1}
print(sorted1) // "[1.2, 1.5, 2.4, 10.9, 20.0]"
print(sorted2) // "[1, 3, 0, 0, 2]"
The above logic can be expanded for three or more arrays:
(slow)
let array1: [Double] = [1.2, 2.4, 20.0, 10.9, 1.5]
let array2: [Int] = [1, 0, 2, 0, 3]
let array3: [Float] = [3.3, 1.1, 2.5, 5.1, 9.0]
// use zip to combine each (first, n.th) array pair and sort that based on the first
let combined12 = zip(array1, array2).sorted(by: {$0.0 < $1.0})
let combined13 = zip(array1, array3).sorted(by: {$0.0 < $1.0})
// use map to extract the individual arrays
let sorted1 = combined12.map {$0.0}
let sorted2 = combined12.map {$0.1}
let sorted3 = combined13.map {$0.1}
As #Duncan C pointed out, this approach is not very efficient as the first array is sorted repeatedly. #vacawama's approach should be used instead, which in Swift 4 syntax is:
(fast)
let offsets = array1.enumerated()sorted(by: {$0.element < $1.element}).map {$0.offset}
let sorted1 = offsets.map {array1[$0]}
let sorted2 = offsets.map {array2[$0]}
let sorted3 = offsets.map {array3[$0]}
Though not especially elegant, a simple solution when working with arrays of objects which must be compared, and whose orders are not known and may not even share the same lengths, is to loop the "ordered" array, finding the matching object in the unordered array, and appending it to a new empty array:
var sorted: [Foo] = []
// Loop the collection whose order will define the other
for item in originalOrder {
// Find the item in the unsorted collection
if let next = unsortedItems.first(where: { $0 === item }) {
// Move the item to the new collection, thus achieving order parity
sorted.append(next)
}
}
This is useful when you have an operation that provides a transformed version of a collection which may have 0..<original.count number of items in any order, and you want to get back to the original order using pointer/object equality.
If you need to additionally maintain index parity, you can skip the if let and just append the result of first(where:) directly into sorted, which will put nil into the blanks.
Note that this example solution will additionally act as a filter for items which are either duplicated or not in the original, which may or may not be what you want. Modify to your needs.

Subtracting elements at specified indices in array

I am beginner to functional programming and Scala. I have an Array of arrays which contain Double numerals. I want to subtract elements (basically two arrays, see example) and I am unable to find online how to do this.
For example, consider
val instance = Array(Array(2.1, 3.4, 5.6),
Array(4.4, 7.8, 6.7))
I want to subtract 4.4 from 2.1, 7.8 from 3.4 and 6.7 from 5.6
Is this possible in Scala?
Apologies if the question seems very basic but any guidance in the right direction would be appreciated. Thank you for your time.
You can use .zip:
scala> instance(1).zip(instance(0)).map{ case (a,b) => a - b}
res3: Array[Double] = Array(2.3000000000000003, 4.4, 1.1000000000000005)
instance(1).zip(instance(0)) makes an array of tuples Array((2.1,4.4), (3.4,7.8), (5.6,6.7))from corresponding pairs in your array
.map{ case (a,b) => a - b} or .map(x => x._1 - x._2) is doing subtraction for every tuple.
I would also recommend to use tuple instead of your top-level array:
val instance = (Array(2.1, 3.4, 5.6), Array(4.4, 7.8, 6.7))
So now, with additional definitions, it looks much better
scala> val (a,b) = instance
a: Array[Double] = Array(2.1, 3.4, 5.6)
b: Array[Double] = Array(4.4, 7.8, 6.7)
scala> val sub = (_: Double) - (_: Double) //defined it as function, not method
sub: (Double, Double) => Double = <function2>
scala> a zip b map sub.tupled
res20: Array[Double] = Array(2.3000000000000003, 4.4, 1.1000000000000005)
*sub.tupled allows sub-function to receive tuple of 2 parameters instead of just two parameters here.

Swift array with mixed elements,why return different result

var arr1: Array = [34, 8.7, "hello"]
var arr2: Array<Any> = [34, 8.7, "hello"]
println(arr1)
println(arr2)
[34, 8.699999999999999, hello]
[34, 8.7, hello]
different result,anyone can explain it?
In the case of arr1, since you didn't specify the type and you have Foundation imported, Swift made the array type [NSObject]. Then, the types of 34, 8.7, and "hello" are NSNumber, NSNumber, and NSString respectively.
For whatever reason, an NSNumber with a value of 8.7 prints as 8.699999999999999. Try this is a Playground:
var a: NSNumber = 8.7
println(a) // prints 8.699999999999999
In arr2, the values have the types Int, Double, and String, so the 8.7 prints as you would expect:
var b: Double = 8.7
println(b) // prints 8.7
As Matt Gibson states in the comments:
the output difference may be because NSNumber's description method
formats the number as "%0.16g"; if you do NSString(format: "%0.16g",
8.7) gives you "8.699999999999999". I'm sure they're both just the same double "underneath".
To test the theory that they are the same number underneath, I did:
if (arr1[1] as NSNumber).doubleValue == (arr2[1] as Double) {
println("same")
}
and this does indeed print "same".

Resources