Is there also a possibility to use the 'where' keyword in another place then a switch? Can I use it in a for in loop for example?
I have an array with bools, all with a value, can I do something like this:
var boolArray: [Bool] = []
//(...) set values and do stuff
for value where value == true in boolArray {
doSomething()
}
This would be a lot nicer than use an if, so I am wondering if there is a possibility to use where in combination with a for-loop. Ty for your time.
In Swift 2, new where syntax was added:
for value in boolArray where value == true {
...
}
In Pre 2.0 one solution would be to call .filter on the array before you iterate it:
for value in boolArray.filter({ $0 == true }) {
doSomething()
}
A normal for-loop will iterate all elements present in the list. But sometimes we want to iterate only when data satisfy some condition, there we can use where clause with for -loop. It's just a replacement of if condition inside the loop.
For example:
let numbers = [1,2,3,4,5,6,7]
for data in numbers {
if (data % 2 == 0) {
print(data)
}
}
can be rewritten in the simpler way as:
for data in numbers where data % 2 == 0 {
print(data)
}
Yes, you can use "where" clause with for loop.
let arr = [1,2,3,4,5]
for value in arr where value != 0 {
print(value)
}
Considering your example,
var boolArray: [Bool] = []
//(...) set values and do stuff
for value in boolArray where value == true {
doSomething()
}
Related
I have a list of A class objects
data class A{
val abc: Abc
val values: Int?
}
val list = List<A>
If I want to count how many objects I have in list I use:
val count= a.count()
or val count= a.count(it -> {})
How to append all values in the list of objects A avoiding for loop? Generaly Im looking for proper kotlin syntax with avoiding code below
if (a!= null) {
for (i in list) {
counter += i.values!!
}
}
Either use sumBy or sum in case you have a list of non-nullable numbers already available, i.e.:
val counter = list.sumBy { it.values ?: 0 }
// or
val counter = extractedNonNullValues.sum()
The latter only makes sense if you already mapped your A.values before to a list of non-nullable values, e.g. something like:
val extractedNonNullValues= list.mapNotNull { it.values } // set somewhere else before because you needed it...
If you do not need such an intermediate extractedNonNullValues-list then just go for the sumBy-variant.
I don't see you doing any appending to a list in the question. Based on your for loop I believe what you meant was "How do I sum properties of objects in my list". If that's the case you can use sumBy, the extension function on list that takes a labmda: ((T) -> Int) and returns an Int like so:
val sum = list.sumBy { a -> a.values ?: 0 }
Also, calling an Int property values is pretty confusing, I think it should be called value. The plural indicates a list...
On another note, there is a possible NPE in your original for loop. Avoid using !! on nullable values as, if the value is null, you will get an NPE. Instead, use null coalescing (aka elvis) operator to fall back to a default value ?: - this is perfectly acceptable in a sum function. If the iteration is not to do with summing, you may need to handle the null case differently.
I have a map that has a few key value pairs, and I would like a way to go through those pairs and attempt to match the keys with the value of another map. If there's a match the values are substituted for each other. In other words, if there's a match value of the second map is substituted for the value of the first map. If there is no match, it is not included in the result.
I've tried figuring out the logic use the scala .map function but I'm new to scala and can't quite figure it out.
For example, I have the following two scala Map[String, String]:
val lookupMap = Map("aaa" -> "apple", "bbb" -> "orange", "ccc" -> "banana")
val entriesMap = Map("foo" -> "ccc", "bar"-> "aaa", "baz" -> "zzz")
I would like some way to get the following result:
val result = Map("foo" -> "banana", "bar" -> "apple")
Note: "baz" was not included because it did not match to anything in the lookup Map.
A for comprehension can clean that up.
val result = for {
(k,ev) <- entriesMap
lv <- lookupMap.get(ev)
} yield (k,lv)
//result: Map[String,String] = Map(foo -> banana, bar -> apple)
Lets break down your problem in simpler steps.
Filter out all pairs on the entriesMap whose value does not exists as a key in the lookupMap.
Map the remaining pairs to change the value for the value on the lookupMap associated with the original value.
Thus, you can write the following:
val result =
entriesMap
.filter { case (_, value) => lookupMap.contains(key = value) }
.map { case (key, value) => key -> lookupMap(value) }
However, every time that you want to filter and then map, you can always use collect (which will do the same job, but in just one iteration).
Thus, you can write this:
val result = entriesMap.collect {
case (key, value) if lookupMap.contains(key = value) => key -> lookupMap(value)
}
Now, one "problem" with the above code is that it uses the unsafe apply over a Map, which will throw an exception if they key does not exists.
Usually, one should use the get method, which would return the value wrapped on an Option, which will be a None if the key did not existed.
In this case, the access is not unsafe, because we are checking if the key exists before.
Anyways, one could rethink the program as:
Map the values of the entriesMap by attempting to get their associated value on the lookupMap.
Filter out the pairs where its values is now a None and unwrapping the Somes.
The code will be as follows:
val result =
entriesMap
.view // Only if you are in 2.13
.mapValues(value => lookupMap.get(key = value))
.collect { case (key, Some(value)) => key -> value }
.toMap // This is necessary because mapValues returns a view, which is a lazy collection.
// Other option would have been to use just map instead of mapValues.
Finally, instead of using higher order functions directly, one could use for comprehension.
Thus, this code (almost the same as the one from jwvh's answer):
val result =
for {
(key, value) <- entriesMap // For each key-value pair in entriesMap...
newValue <- lookupMap.get(key = value) // And for each newValue associated with each original value...
} yield key -> newValue // Yield the key-newValue pair.
In my imperative-style Scala code, I have an algorithm:
def myProcessor(val items: List) {
var numProcessed = 0
while(numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
numProcessed += processNextBlockOfItems(items, processedSoFar)
}
}
I would like to keep the "block processing" functionality, and not just do a "takeWhile" on the items list. How can I rewrite this in functional style?
You need to change it to a recursive style wherein you "pass" in the "state" of each loop
#tailrec
def myProcessor(items: List[A], count: Int = 0): Int = items match{
case Nil => count
case x :: xs =>
processNextBlockOfItems(items, count)
myProcessor(xs, count + 1)
}
assuming that "processedSoFar" is not an index. If you can work with the current "head" of the list:
#tailrec
def myProcessor(items: List[A], count: Int = 0): Int = items match{
case Nil => count
case x :: xs =>
process(x)
myProcessor(xs, count + 1)
}
where process would only process the current "head" of the List.
So, this depends on what you consider to be more functional, but here's a version without the 'var'
def myProcessorFunctional(items: List[Int]) {
def myProcessorHelper(items: List[Int], numProcessed: Int) {
if (numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
myProcessorHelper(items,
numProcessed + processNextBlockOfItems(items, processedSoFar))
}
}
myProcessorHelper(items, 0)
}
(making it a list of Ints just for simplicity, it would be easy to make it work with a generic List)
I have to say it's one of those cases where I don't mind the mutable variable - it's clear, no reference to it escapes the method.
But as I said in a comment above, processNextBlockOfItems is inherently non-functional anyway, since it's called for its side effects. A more functional way would be for it to return the state of its processing so far, and this state would be updated (and returned) on a subsequent call. Right now, if you in the middle of processing two different items lists, you'd have the issue of maintaining two different partially-processed states within processNextBlockOfItems...
Later:
Still ignoring the state issue, one convenient change would be if processNextBlockOfItems always processed the first block of the items list passed to it, returned the remaining items it had not processed (this is convenient and efficient if using List, so much so I'm wondering why you're using indicies).
This would yield something like:
def myProcessorMoreFunctional(items: List[Int]) {
if (!items.isEmpty) {
myProcessorMoreFunctional(processNextBlockOfItems(items))
}
}
To me this makes perfect sense:
triple = dice.collect {|value| if (dice.count(value) >= 3)} ---> Syntax error
OR
triple = dice.collect {|value| dice.count(value) >= 3} ----> Array of true/false
I want the value of the number, not the true or falsity of dice.count(). I know there must be a simple way of doing this.
It sounds like you want Array#select, not Array#collect (also known as Array#map).
collect/map will take each value and put the results of your block into an array. This is why you're seeing an array of true/false.
select will take each value, and return it as a member of an array if the block evaluates to true:
triple = dice.select{ |value| dice.count(value) >= 3 }
Your block needs to return whatever it is you want in the final array.
triple = dice.collect {|value|
if dice.count(value) >= 3
dice.count(value)
end
}
Note that this will return nil for elements < 3 (though you can add an else to return 0 or something). If you only want elements that match your query, you'll need to use dice.select()
As for your first code snippet,
triple = dice.collect {|value| THE_CODE_BLOCK_STARTS_HERE }
Thus, if (dice.count(value) >= 3) is an incomplete if statement. That's why you get syntax error.
I need to write a code snippet that would compare multiple arrays and produce the set that match the data in those arrays, produce the data set only in array A, but not in array B,C,D,in array B but not in A,C,D, being able to handle any number of arrays (i.e. dynamically looped). The code should utilize anonymous functions in Scala (i.e. not like a regular array looping like in Java).
Sounds like homework to me. By far the easiest way to do this is to throw the contents of array A into a Set and use the remove operation. This would be O(n) where n = \sum { |A|, |B|, |C|, ... }. The following solution works for arbitrary Iterable, not just Array:
def compareArrays[A](arrs: List[Iterable[A]]) = arrs match {
case a :: tail => {
val set = a.foldLeft(Set[A]()) { _ + _ }
tail.foldLeft(set) { _ -- _ }
}
case Nil => Nil
}