Kotlin how to split a list in to sublists - kotlin

I would like to split a list into a few sublists, but I have no idea how to do it.
Once of my ideas was splitting the list by index of element. For exmaple "B" index is 0, "S" index 2, so I would like to take a part between index 0 - 1 into the first sublist, then the second sublist should be the part between index 2 - 5.
Example of my list:
val listOfObj = listOf("B", "B" , "S", "B", "B", "X", "S", "B", "B", "P")
Result after splitting:
listOf(listOf("B","B"), listOf("S", "B", "B", "X"), listOf("S", "B", "B", "P") )
How do I achieve such a result?

Here it goes. I wrote it from my phone without checking but the idea is basic.
val result = mutableListOf<List<String>>()
var current = mutableList<String>()
listOfObj.forEach { letter ->
if (letter == "S") {
result.add(current)
current = mutableListOf<String>()
}
current.add(letter)
}
if (current.isNotEmpty()) {
result.add(current)
}
You can even create an extension function for a List<T> that gets a separator element as a parameter and returns a list of lists.

Related

Dynamic CSV with Header only once

I have a request to parse a JSON payload and then create columns dynamically based on a condition.
There should be a Groups column with header. For any additional groups the employee is in, they will be in a column with no header.
If the member is in one group it makes sense I can do something like the following:
%dw 2.0
output application/csv separator=","
var employeesPayload = payload
---
employeesPayload filter ($.workEmail != '' and $.companyEmploymentType.isContractor == false) map (employee) -> {
"Employee ID": employee.employeeNumber,
"Name": employee.preferredFirstName default employee.firstName ++ ' ' ++ if (employee.preferredLastName == '' or employee.preferredLastName == null) employee.lastName else employee.preferredLastName,
"Email": employee.workEmail,
"Groups": employee.workState
}
i.e the table should look similar to the following:
But, how do I add additional columns without headers?
i.e if I want to add a user like Tito (row 9) in the screenshot, how can I build this dynamically?
You can add additional fields dynamically by mapping the payload. If you want the header to be empty you can set the key to an empty string. Note that you can not skip columns, if there is no content you need to at least output an empty string.
Example:
%dw 2.0
output application/csv
---
payload map {
($), // just reusing the input payload as is
d: $$, // some calculated field with a header
"": if (isEven($$)) $$ else "", // calculated field with an empty name, only on some condition
"": $$ // another calculated field with an empty name
}
Input:
[
{
"a": "a1",
"b": "b1",
"c": "c1"
},
{
"a": "a2",
"b": "b2",
"c": "c2"
},
{
"a": "a3",
"b": "b3",
"c": "c3"
}
]
Output:
a,b,c,d,,
a1,b1,c1,0,0,0
a2,b2,c2,1,,1
a3,b3,c3,2,2,2

Display discrepancies between collections

When asserting the equality of two string collections using
collectionA.Should().Equal(collectionB) the message is:
"Expected collectionA to be equal to {"a", "b", "c", …5 more…} , but {"a", "b", "c", …13 more…} contains 8 item(s) too many."
Is there a way to display the actual discrepancies between the collections?

I have two lists of strings in kotlin, how to concatenate each element of the first list with elements of the second one respective to the positions?

I have two lists:
val a = listOf("a", "b", "c")
val b = listOf("1", "2", "3")
I want to get a list that looks like this: ["a1", "b2", "c3"].
How to do this in the most efficient way?
The easiest way would look like this:
val c = a.zip(b).map {it.first + it.second }

Lucene: TokenFilter to replace chars and produce new tokens as synonyms

I want to map chars like this:
private static final Map<String, String> MAP = Map.of("CH", "X",
"X", "CH",
"I", "Y",
"Y", "I",
"S", "Z",
"Z", "S",
"F", "PH",
"PH", "F");
So for ex, XANTION is tokenized to CHANTION, PHYTOVEIN is tokenized to FITOVEIN, keeping original tokens.
Those are medicine names, it would generate "synonyms" for those, to use when analyzing search terms.
Could I use any existing token filter?

Kotlin: functional way to split list into grouped lists [duplicate]

This question already has answers here:
How to split a list into sublists using a predicate with Kotlin?
(2 answers)
Closed 1 year ago.
I want to group specific items in a list based on a 'split predicate'. An example of what I mean:
val list = listOf("1", "2", "3", "", "4", "5", "6", "", "7")
// looking for: a nice readable (maybe functional?) way to get to:
val result = listOf(
listOf("1", "2", "3"),
listOf("4", "5", "6"),
listOf("7"),
)
As you see, I want to split the list on items which are item.isBlank() - which I also want to drop in the process.
I know how to do it imperatively, but I think there must be a nice, readable, functional way!
Thanks a lot & regards
Marc
I had a solution that is similar to Matt's (had to run to a meeting and couldn't post it earlier!). It is materially the same, but allows you to specify an arbitrary predicate to split on, accounts for the fact that you might start with a blank item and end up with an unwanted empty list (or if you have two items that match the predicate in a row), and is defined as an extension function:
fun <T> List<T>.split(predicate: (T) -> Boolean): List<List<T>> =
fold(mutableListOf(mutableListOf<T>())) { acc, t ->
if (predicate(t)) acc.add(mutableListOf())
else acc.last().add(t)
acc
}.filterNot { it.isEmpty() }
And to call it:
list.split { it.isBlank() }
// Returns [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
There's probably a cleaner way but I think this solves it
list.fold (mutableListOf(mutableListOf<String>())) { acc, item ->
if (item.isBlank()) {
acc.add(mutableListOf())
} else {
acc.last().add(item)
}
acc
}