How to add new item in specific index? - collections

I new in kotlin , i want to update an item in lists.
I use this code:
var index: Int
for (record in recordList)
if (record.id == updatedHeader?.id) {
index = recordList.indexOf(record)
recordList.add(index, updatedHeader)
}
but it cant do this, because of ConcurrentModificationException

Assuming that recordList is a MutableList and val (so, you'd like to modify the records in place), you can use forEachIndexed to find the records you care about and replace them.
This did not cause a ConcurrentModificationException:
recordList.forEachIndexed { index, record ->
if(record.id == updatedHeader?.id) recordList[index] = updatedHeader
}
On the other hand, if you redefine recordList as a non-mutable list, and a var, you could rewrite the entire list using map:
recordList = recordList.map { if(it.id == updatedHeader?.id) updatedHeader else it }
Of course, you could call .toMutableList() on the end of that if you wanted to turn your List into a MutableList.

If there's a single record with the given id in the list, you can find its index and add the header at that index:
val index = recordList.indexOfFirst { it.id == updatedHeader.id }
if (index >= 0)
recordList.add(index, updatedHeader)
If there are multiple records with the given id and you want to prepend header before each of them, you can use get listIterator and use its methods to modify the list during the iteration without getting ConcurrentModificationException:
val iterator = recordList.listIterator()
for (record in iterator) {
if (record.id == updatedHeader.id) {
iterator.previous() // move to the position before the record
iterator.add(updatedHeader) // prepend header
iterator.next() // move next, back to the record
}
}

Related

How to add any symbols after prefix_?

is there any solution? e.g. I have data in Map with key favorites_ prefix and values _suffix (for example: favorites_jeans, favorites_suit,...,). I want to by dint of loop get that values and set in List, because of it I must give keys of map, right?
I want to know how can I get values of myMap["favorites_*"] (* - after the favorites_ any symbols).
List<String> favoritesStrings = ['favorite_name','favorite_jeans',];
Map<String,dynamic> myMap = {
favoritesStrings[0]:'0',
favoritesStrings[1]:'1',
'someKey':'2',
'anotherKey':'3',
};
favoritesStrings.forEach((favorite)=>print(myMap[favorite]));//prints 0 1
As per what I understood, you want to fetch value from map using "favorites_" + a dynamic value from list as key.
You just have to use String templates and use $ to insert suffix variable to build key dynamically:
List<String> suffixList = ["jeans", "suit", "shirt"];
for(String suffix in suffixList) {
var item = myMap["favorites_$suffix"];
// Do something with item
}
Hope it helps

kotlin adding pair to map when value is a list

I know this is basic but can I do this in a shorter way:
val ss = mutableMapOf<String, MutableList<String>>()
if(ss["new_key"] != null){
ss["new_key"]!!.add("NEW")
}
else{
ss["new_key"] = mutableListOf("OLD")
}
This basically checks if the key exists in the map
if it does an element is appended to the list(value) otherwise a new key-value pair is created
Can't I create a new key on the go? like this:
ss["new_key"].add("OLD")
ss["new_key"].add("NEW")
You have at least 2 options:
use computeIfAbsent:
ss.computeIfAbsent("new_key") { mutableListOf() } += "NEW"
use getOrPut:
ss.getOrPut("new_key", ::mutableListOf) += "NEW"

How do I make UpdateOrInsert in Kotlin collections

I have a list of items, and one of item copies is changed by user, how do I find it in my collection by Id and update, or if it's not found I'd like to add the item? my best guess is, but it requires ugly indexOf(v)
fun updateOrInsert(note : UserNote) {
val list = notes.value!!
val v = list.firstOrNull{(Id) -> Id ==note.Id}
if (v==null) {
list.add(note)
} else {
val i = list.indexOf(v)
list[i] = note
}
notes.value = list
}
Use indexOfFirst to find the index of the first element with the given ID. If -1, add the item to the list, otherwise, change the value at the found index.

Groovy: Transforming a String into a Multimap

So I have a String which looks a little something like this:
text = "foo/bar;baz/qux"
My end goal is to split this String into a Multimap like this:
["level1" : ["foo", "baz"], "level2" : ["bar", "qux"]]
I also added Multimap-support to LinkedHashMap's metaClass:
LinkedHashMap.metaClass.multiPut << { key, value ->
delegate[key] = delegate[key] ?: []; delegate[key] += value
}
The String needs to be split at semi-colon and then again at forwardslash. Currently I'm populating my Multimap within a nested for-loop but obviously there's a Groovier way of doing this. Thus I was wondering what my options are?
I'm thinking something along the lines of:
def final myMap = text.split(';')
.collectEntries { it.split('/')
.eachWithIndex { entry, index -> ["level${index + 1}" : entry] }}
You can use withDefault on your returned Map to get rid of the ternary:
def text = "foo/bar;baz/qux;foo/bar/woo"
def result = text.split(';')*.split('/').inject([:].withDefault {[]}) { map, value ->
value.eachWithIndex { element, idx ->
map["level${idx+1}"] << element
}
map
}
assert result == [level1:['foo', 'baz', 'foo'], level2:['bar', 'qux', 'bar'], level3:['woo']]
If you don't want duplicates in your results, then you can use a Set in your withDefault (then convert back to a List afterwards):
def text = "foo/bar;baz/qux;foo/bar/woo"
def result = text.split(';')*.split('/').inject([:].withDefault {[] as Set}) { map, value ->
value.eachWithIndex { element, idx ->
map["level${idx+1}"] << element
}
map
}.collectEntries { key, value -> [key, value as List] }
assert result == [level1:['foo', 'baz'], level2:['bar', 'qux'], level3:['woo']]
My take on it, I wouldn't consider it very clever but I find it much easier to read:
def myMap = [:]
text.split(';').eachWithIndex{ entry, index ->
myMap << ["level${index + 1}": entry.split('/')]
}
If you are using Groovy 2.4.0 or above, you could use the withIndex() method which has been added to java.lang.Iterable:
def myMap = text.split(';').withIndex().collect{ entry, index ->
["level${index + 1}": entry.split('/')]
}

Faster database access by index

I have this code
using (var contents = connection.CreateCommand())
{
contents.CommandText = "SELECT [subject],[note] FROM tasks";
var r = contents.ExecuteReader();
int zaehler = 0;
int zielzahl = 5;
while (r.Read())
{
if (zaehler == zielzahl)
{
//access r["subject"].ToString()
}
zaehler++;
}
}
I want to make it faster by accessing zielzahl directly like r[zielzahl] instead of iterating through all entries. But
r[zielzahl]["subject"]
does not work aswell as
r["subject"][zielzahl]
How do I access the column subject of result number zielzahl?
To get only the sixth record, use the OFFSET clause:
SELECT subject, note
FROM tasks
LIMIT 1 OFFSET 5
Please note that the order of returned records is not guaranteed unless you use the ORDER BY clause.

Resources