Kotlin sumBy function with condition - string

Instead of using ifs and loops I would like to use sumBy function and give it a statement. Where to add condition?
val counter = list.sumBy {it.amount}
where amount is field from the list.
Where to add for example if(it.flag == true) statement?
Or just use streams?

val counter = list.sumBy { if (it.flag) it.amount else 0 }
or
val counter = list.asSequence().filter { it.flag }.sumBy { it.amount }
asSequence() for using sequence to prevent creataion an intermediate collection in filter function

If you have an array by name "amount" the list then items sum will we done by this method.
val amount= listOf(10, 20, 30)
println(amount.sumBy { it })

Related

Find matches in different indices in String. Kotlin

I have two lines of the same length. I need to get the number of letters that match as letters and have different index in the string (without nesting loop into loop). How I can do it?
Would the following function work for you?
fun check(s1: String, s2: String): Int {
var count = 0
s2.forEachIndexed { index, c ->
if (s1.contains(c) && s1[index] != c) count++
}
return count
}
See it working here
Edit:
Alternatively, you could do it like this if you want a one-liner
val count = s1.zip(s2){a,b -> s1.contains(b) && a != b}.count{it}
where s1 and s2 are the 2 strings

Kotlin HashMap contain keys using an array

Is there any way to check a HashMap if it contains a certain set of keys which keys are given in an array. When I try something like the code below it returns false.
map.containsKey(arrayOf("2018-01-16"))
If I try the following code it works but I need to check for the keys and the numbers of keys that I need to search is not fixed.
map.containsKey("2018-01-16")
You can start from the keys themselves, and use the all function from the standard library:
val map = hashMapOf(...)
val keys = arrayOf("2018-01-16", "2018-01-17", "2018-01-18")
val containsAllKeys = keys.all { map.containsKey(it) }
If you do this a lot and want to have this functionality on the Map type, you can always add it as an extension:
fun <K, V> Map<K, V>.containsKeys(keys: Array<K>) = keys.all { this.containsKey(it) }
val containsAllKeys = map.containsKeys(arrayOf("2018-01-16", "2018-01-17"))
You might also want to overload the extension with another function that takes an Iterable<K> as the parameter.
Map has keys collection, which as every collection implements containsAll method, so you can use it to check whether the keys collection contains all of the keys:
map.keys.containsAll(keysArray.asList())
You could use ArrayList<T> as a key, since it's equals is different as the Array<T> one. Let's see this test:
class ExampleUnitTest {
#Test
fun arrayAsKeyTest() {
val hashMapOne = HashMap<Array<String>, Int>()
val stringKeysOne1 = arrayOf("a", "b")
hashMapOne.set(stringKeysOne1, 2)
val stringKeysOne2 = arrayOf("a", "b")
// NOT MATCH! As stringKeysOne1 == stringKeysOne2 is false
assertFalse(hashMapOne.containsKey(stringKeysOne2)) // NOT MATCH
val hashMapTwo = HashMap<ArrayList<String>, Int>()
val stringKeysTwo1 = arrayListOf("a", "b")
hashMapTwo.set(stringKeysTwo1, 2)
val stringKeysTwo2 = arrayListOf("a", "b")
// MATCH! As stringKeysTwo1 == stringKeysTwo2 is true (although stringKeysTwo1 === stringKeysTwo2 is false)
assertTrue(hashMapTwo.containsKey(stringKeysTwo2)) // MATCH
}
}

Scala: convert each digit in a string to an integer

I want to convert each digit in a number to an int. Here is my code
for (in <- lines) {
for (c <- in) {
val ci = c.toInt
if (ci == 0) {
// do stuff
}
}
}
The result I get is the ascii code, i.e. a 1 gives 49. I'm looking for the value 1.
The answer is trivial, I know. I'm trying to pull myself up with my own bootstraps until my Scala course begins in two weeks. Any assistance gratefully accepted.
One possible solution is:
for(in <- lines) {
in.toString.map(_.asDigit).foreach { i =>
if(i == 1) {
//do stuff
}
}
}
And more compact w/ output:
lines.foreach(in => in.toString.map(_.asDigit).filter(_ == 1).foreach(i => println(s"found $i in $in.")))
If lines is already a collection of Strings, omit the .toString on in.toString.
You can have this:
val number = 123456
//convert Int to String and do transformation for each character to Digit(Int)
val digitsAsList = number.toString.map(_.asDigit)
This will result to digitizing the number. Then with that Collection, you can do anything from filtering, mapping, zipping: you can checkout the the List api on this page: http://www.scala-lang.org/api/2.11.8/#scala.collection.immutable.List
Hope that's help.

Scala split string and sort data

Hi I am new in scala and I achieved following things in scala, my string contain following data
CLASS: Win32_PerfFormattedData_PerfProc_Process$$(null)|CreatingProcessID|Description|ElapsedTime|Frequency_Object|Frequency_PerfTime|Frequency_Sys100NS|HandleCount|IDProcess|IODataBytesPersec|IODataOperationsPersec|IOOtherBytesPersec|IOOtherOperationsPersec|IOReadBytesPersec|IOReadOperationsPersec|IOWriteBytesPersec|IOWriteOperationsPersec|Name|PageFaultsPersec|PageFileBytes|PageFileBytesPeak|PercentPrivilegedTime|PercentProcessorTime|PercentUserTime|PoolNonpagedBytes|PoolPagedBytes|PriorityBase|PrivateBytes|ThreadCount|Timestamp_Object|Timestamp_PerfTime|Timestamp_Sys100NS|VirtualBytes|VirtualBytesPeak|WorkingSet|WorkingSetPeak|WorkingSetPrivate$$(null)|0|(null)|8300717|0|0|0|0|0|0|0|0|0|0|0|0|0|Idle|0|0|0|100|100|0|0|0|0|0|8|0|0|0|0|0|24576|24576|24576$$(null)|0|(null)|8300717|0|0|0|578|4|0|0|0|0|0|0|0|0|System|0|114688|274432|17|0|0|0|0|8|114688|124|0|0|0|3469312|8908800|311296|5693440|61440$$(null)|4|(null)|8300717|0|0|0|42|280|0|0|0|0|0|0|0|0|smss|0|782336|884736|110|0|0|1864|10664|11|782336|3|0|0|0|5701632|19357696|1388544|1417216|700416$$(null)|372|(null)|8300715|0|0|0|1438|380|0|0|0|0|0|0|0|0|csrss|0|3624960|3747840|0|0|0|15008|157544|13|3624960|10|0|0|0|54886400|55345152|5586944|5648384|2838528$$(null)|424|(null)|8300714|0|0|0|71|432|0|0|0|0|0|0|0|0|csrss#1|0|8605696|8728576|0|0|0|8720|96384|13|8605696|9|0|0|0|50515968|50909184|7438336|9342976|4972544
now I want to find data who's value is PercentProcessorTime, ElapsedTime,.. so for this I first split above string $$ and then again split string using | and this new split string I searched string where PercentProcessorTime' presents and get Index of that string when I get string then skipped first two arrays which split from$$and get data ofPercentProcessorTime` using index , it's looks like complicated but I think following code should helps
// First split string as below
val processData = winProcessData.split("\\$\\$")
// get index here
val getIndex: Int = processData.find(part => part.contains("PercentProcessorTime"))
.map {
case getData =>
getData
} match {
case Some(s) => s.split("\\|").indexOf("PercentProcessorTime")
case None => -1
}
val getIndexOfElapsedTime: Int = processData.find(part => part.contains("ElapsedTime"))
.map {
case getData =>
getData
} match {
case Some(s) => s.split("\\|").indexOf("ElapsedTime")
case None => -1
}
// now fetch data of above index as below
for (i <- 2 to (processData.length - 1)) {
val getValues = processData(i).split("\\|")
val getPercentProcessTime = getValues(getIndex).toFloat
val getElapsedTime = getValues(getIndexOfElapsedTime).toFloat
Logger.info("("+getPercentProcessTime+","+getElapsedTime+"),")
}
Now Problem is that using above code I was getting data of given key in index, so my output was (8300717,100),(8300717,17)(8300717,110)... Now I want sort this data using getPercentProcessTime so my output should be (8300717,110),(8300717,100)(8300717,17)...
and that data should be in lists so I will pass list to case class.
Are you find PercentProcessorTime or PercentPrivilegedTime ?
Here it is
val str = "your very long string"
val heads = Seq("PercentPrivilegedTime", "ElapsedTime")
val Array(elap, perc) = str.split("\\$\\$").tail.map(_.split("\\|"))
.transpose.filter(x => heads.contains(x.head))
//elap: Array[String] = Array(ElapsedTime, 8300717, 8300717, 8300717, 8300715, 8300714)
//perc: Array[String] = Array(PercentPrivilegedTime, 100, 17, 110, 0, 0)
val res = (elap.tail, perc.tail).zipped.toList.sortBy(-_._2.toInt)
//List[(String, String)] = List((8300717,110), (8300717,100), (8300717,17), (8300715,0), (8300714,0))

Linq to split/analyse substrings

I have got a List of strings like:
String1
String1.String2
String1.String2.String3
Other1
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB
Folder1.Folder2.FolderB.FolderC
Now I would like to group this into:
String1.String2.String3
Other1.Other2
Test1
Stuff1.Stuff1
Text1.Text2.Text3
Folder1.Folder2.FolderA
Folder1.Folder2.FolderB.FolderC
If
"String1" is in the next item "String1.String2" I will ignore the first one
and if the second item is in the third I will only take the third "String1.String2.String3"
and so on (n items). The string is structured like a node/path and could be split by a dot.
As you can see for the Folder example Folder2 has got two different Subfolder items so I would need both strings.
Do you know how to handle this with Linq? I would prefer VB.Net but C# is also ok.
Regards Athu
Dim r = input.Where(Function(e, i) i = input.Count - 1 OrElse Not input(i + 1).StartsWith(e + ".")).ToList()
Condition within Where method checks if element is last from input or is not followed by element, that contains current one.
That solution uses the fact, that input is List(Of String), so Count and input(i+1) are available on O(1) time.
LINQ isn't really the correct approach here, because you need to access more than one item at a time.
I would go with something like this:
public static IEnumerable<string> Filter(this IEnumerable<string> source)
{
string previous = null;
foreach(var current in source)
{
if(previous != null && !current.Contains(previous))
yield return previous;
previous = current;
}
yield return previous;
}
Usage:
var result = strings.Filter();
Pretty simple one. Try this:
var lst = new List<string> { /*...*/ };
var sorted =
from item in lst
where lst.Last() == item || !lst[lst.IndexOf(item) + 1].Contains(item)
select item;
the following simple line can do the trick, I'm not sure about the performance cost through
List<string> someStuff = new List<string>();
//Code to the strings here, code not added for brewity
IEnumerable<string> result = someStuff.Where(s => someStuff.Count(x => x.StartsWith(s)) == 1);

Resources