The enumerate function returns a tuple for each item in the array composed of the index and the value for that item.
The map function returns an array of elements built from the results of applying a provided transforming closure for each element in the array.
Declaration:
func map<U>(transform: (T) -> U) -> [U]
var numbers = [1, 2, 3]
numbers = map(numbers) { (index, element) in
index + element
} //[1, 3, 5]
That is good. Works.
var numbers = [1, 2, 3]
var result = map(enumerate(numbers)) { (index, element) in
index + element
} //[1, 3, 5]
map expects an array as a first parameter, but I put there the tuple as a result of enumerate fnction.
The question is: WHY IT WORKS?
It works because in addition to array having a map method, there is a map function that takes any kind of SequenceType:
func map<S : SequenceType, T>(source: S, transform: (S.Generator.Element) -> T) -> [T]
This works not just with arrays, but any kind of sequence – strings, ranges, zipped pairs of sequences, and the result of enumerate, which is also a sequence:
// enumerate is a function that takes any kind of sequence, and returns
// an EnumerateSequence object
func enumerate<Seq : SequenceType>(base: Seq) -> EnumerateSequence<Seq>
EnumerateSequence is a type that holds on to another sequence (in your case, the array [1,2,3]) and then when asked to generate an element, generates the next element from it’s contained sequence along with an incrementing number.
You want to look at the following answer: What's the cleanest way of applying map() to a dictionary in Swift?
The map function works on the tuple because it is using the map function from the swift standard library that works on any SequenceType. So it is actually using the index and value of the enumeration, which are the same as the index and element that the map function would use when looking at an array input.
Related
Is there a way to check a condition within a foreach loop in scala. The example is that I want to go through an array of integers and do some arbitrary math on the positive numbers.
val arr = Array(-1,2,3,0,-7,4) //The array
//What I want to do but doesn't work
arr.foreach{if(/*This condition is true*/)
{/*Do some math and print the answer*/}}
//Expected answer for division by six is 0.333333333 \n 0.5 \n 0.666666667
//Which is 2/6, 3/6 and 4/6 respectively as they appear in the array
I know how to do it with a normal for loop and if statement but I want to use this because I want to get away from java.
Thanks
foreach function brings every item in the list/array one by one, you should set it to a variable before to use it.
For example:
arr.foreach( variable_name => {
if(/*This condition is true*/){
/*Do some math and print the answer*/
}
})
The argument to foreach is a function, taking one argument, and returning a Unit. The argument is current element of the list, as it has been pointed out in other answers. You can just give it a name, and reference it as you would any other variable.
arr.foreach { x => if(x > 0) println(x/6.0) }
It is generally better and more idiomatic to split your logic into a chain of simpler "atomic" transformations rather than putting everything into one long function:
arr
.iterator
.filter(_ > 0)
.map(_ / 6.0)
.foreach(println)
The underscore _ above is shorthand for the function argument. You can use it in short functions when you only need to reference the argument once, and a few other conditions are satisfied. The last line doesn't need to pass the argument to println, because println itself is a function, being passed to foreach. I could write it as .foreach(println(_)) or .foreach(x => println(x)), it would do the same thing, but is technically a little different: this form creates an anonymous function like def foo(x: Double) { println(x) } and passes it to foreach as an argument, the way I wrote it originally, just passes println itself as an argument.
Also, note a call to .iterator in the beginning. Everything would work the same way if you take it out. The difference is that iterators are lazy. The way it is written, the code will take first argument from the array, send it through filter, if it returns false, it'll stop, and go back to the second element, if filter returns true, it'll send that element to map, then print it out, then go back, grab the next element etc.
Without .iterator call, it'd work differently: first, it would run the entire array through filter, and create a new array, containing only positive numbers, then, it'd run that new array through map, and create a new one, with the numbers divided by 6, then it'd go through this last array to print out the values. Using .iterator makes it more efficient by avoiding all the intermediate copies.
First, you'll want to use map() instead of foreach() because map() returns a result whereas foreach() does not and can only be used for side effects (which should be avoided when possible).
As has been pointed out, you can filter() before the map(), or you can combine them using collect().
arr.collect{case x if x > 0 => x/6.0}
// res0: Array[Double] = Array(0.3333333333333333, 0.5, 0.6666666666666666)
Use the filter function before using the foreach.
arr.filter(_ > 0).foreach { value => ... }
var list: ListSet[Int] = ListSet(-1, -5, -3, 8, 7, 9, 4, 6, 2, 1, 0)
list.filter(p => p > 5).foreach(f => {
print(f + " ")
})
Output : 8 7 9 6
Just do a filter and a map.
Don't forget that scala consider the array you want as Array[Int], so if you apply /6, you gonna have 0, ensure the cast by add .toDouble
val arr = Array(-1,2,3,0,-7,4)
val res = arr.filter(_>0).map(_.toDouble/6)
res.foreach(println)
Result:
0.3333333333333333
0.5
0.6666666666666666
I am trying to determine what the type of .map's output is here:
func position(rows: Int, cols: Int) -> [Position] {
return (0 ..< rows)
.map {
zip(
[Int](repeating: $0, count: cols) ,
0 ..< cols
)
}
}
I know that zip returns a Zip2Sequence instance, which in this case is tuple pairs of (integer array, countable integer range).
I get that map alters elements in a sequence, but I thought it took multiple arguments like val in val * 2 and here zip is the only argument... so is it just adding the output of zip to an array?
The result of the map is of type Array<Zip2Sequence<Array<Int>, CountableRange<Int>>> which is essentially [[(Int, Int)]].
I found this by assigning the result of the map to let result and printing print(type(of: result)).
map transforms your original sequence (0 ..< rows) into an array that will have rows items. zip will be called with each element of (0 ..< rows) in turn which is represented by $0.
It will be more useful if you wrap the zip call with Array() to turn the zip sequence into an actual array that you can examine easily:
Example:
let rows = 2
let cols = 3
let result = (0 ..< rows)
.map { val in
Array(zip(
[Int](repeating: val, count: cols) ,
0 ..< cols
))
}
print(result)
// [[(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1), (1, 2)]]
The type of (0 ..< rows) is CountableRange<Int>:
1> (0 ..< 10)
$R0: (CountableRange<Int>) = {
lowerBound = 0
upperBound = 10
}
CountableRange conforms to Sequence, so it has a map method. This map method takes one argument, a closure.
A closure is a function. In general, a function has zero or more arguments and a one return value. For CountableRange<Int>.map, the closure is required to take one argument of type Int and can return any type.
There are several ways to write closures in Swift. The shortest way, which your example uses, is to write a single expression inside { ... }. Here's what The Swift Programming Language (Swift 4) says:
Implicit Returns from Single-Expression Closures
Single-expression closures can implicitly return the result of their single expression by omitting the return keyword from their declaration[…]
Furthermore, if the closure takes arguments, the closure can refer to them using shorthand names ($0, $1, etc.) instead of giving them explicit names (e.g. val in ...). From the book again:
Shorthand Argument Names
Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.
If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted, because the closure expression is made up entirely of its body[…]
Looking at the map method call, we can see that its closure contains a single expression (a call to zip) with implicit return, and it uses $0 to refer to its single argument.
The zip function takes two arguments, each of which must be a Sequence, and the zip function returns a Zip2Sequence. In your example, the first argument to zip is [Int](repeating: $0, count: cols), which has type [Int] (or Array<Int>). The second argument to zip is 0 ..< cols, which is another CountableRange<Int>. So the type returned by this call to zip is Zip2Sequence<[Int], CountableRange<Int>>, which is a somewhat inscrutable type that generates tuples (Int, Int).
The type returned by map is an Array containing the values returned by its closure argument. Thus the type returned by map in this case is [Zip2Sequence<[Int], CountableRange<Int>>].
If you want something more scrutable, you can wrap the call to zip in the Array constructor:
func position(rows: Int, cols: Int) -> [[(Int, Int)]] {
return (0 ..< rows)
.map {
Array(zip(
[Int](repeating: $0, count: cols) ,
0 ..< cols
))
}
}
The Array constructor takes any Sequence and turns it into an Array. So the Zip2Sequence<[Int], CountableRange<Int>> is turned into [(Int, Int)], and map produces an Array whose elements are that type, thus producing an array of arrays of pairs of Int, or [[(Int, Int)]].
Am trying to convert a map to list of Tuples, given a map like below
Map("a"->2,"a"->4,"a"->5,"b"->6,"b"->1,"c"->3)
i want output like
List(("a",2),("a",4),("a",5),("b",6),("b",1),("c",3))
I tried following
val seq = inputMap.toList //output (a,5)(b,1)(c,3)
var list:List[(String,Int)] = Nil
for((k,v)<-inputMap){
(k,v) :: list
} //output (a,5)(b,1)(c,3)
Why does it remove duplicates? I dont see other tuples that has "a" as key.
That's because a Map doesn't allow duplicate keys:
val map = Map("a"->2,"a"->4,"a"->5,"b"->6,"b"->1,"c"->3)
println(map) // Map(a -> 5, b -> 1, c -> 3)
Since map has duplicate keys, it will remove duplicate entries while map creation itself.
Map("a"->2,"a"->4,"a"->5,"b"->6,"b"->1,"c"->3)
it will turn into,
Map(a -> 5, b -> 1, c -> 3)
so other operations will be performed on short map
The problem is with Map, whose keys are a Set, so you cannot have twice the same key. This is because Maps are dictionaries, which are made to access a value by its key, so keys MUST be unique. The builder thus keeps only the last value given with the key "a".
By the way, Map already has a method toList, that do exactly what you implemented.
In Swift, i.e. a tuple let tp = (2,5,8).
What's the simplest and smartest way to sum it up, other than traditionaly as below?
let sum = tp.0 + tp.1 + tp.2
Your approach is the most straightforward. An alternative is harder to read, but it works, too:
let s = Mirror(reflecting: x).children.map {$1 as! Int}.reduce(0,+)
Mirror(reflecting: x).children obtains a sequence of name-value pairs representing the original tuple. Each element of the sequence is a (String,Any) tuple. map {$1 as! Int} converts this sequence to a sequence of Ints representing tuple element values; reduce(0,+) produces the sum of these values.
You can combine map and reduce in a single expression for something even less readable:
let s = Mirror(reflecting: x).children.reduce(0,{$0.1.value as! Int + $0.0})
Note: It goes without saying that this crashes at runtime for tuples containing values of type other than Int.
I was wondering if there is a method or function in Swift which can count the number of elements in the tuple.
Reason of question:
I have a tuple called "tople"
What I want to do is to load the elements into variables (by using for loop, where you actually need the number of elements)
And then use this in a function.
Additional questions, can you use tuples to load variables into the function and/or to return them from a function?
var tople = (1,2,3)
func funkce (a:Int, b:Int, c: Int){
println(a)
println(b)
println(c)
}
funkce(a,b,c)
Thanks and I do appreciate any helpful comment.
In Swift 3 you count the number of elements in a tuple like this:
let myTuple = (1,2,3,4)
let size = Mirror(reflecting: myTuple).children.count
Yes, you can load tuples into variables.
let (a, b, c) = (1, 2, 3)
To extract values from a tuple, you can use MirrorType. You can find more here.
let tuple = (1, 2, 3)
let count = Mirror(reflecting: tuple).children.count // 3