How to reverse a Map in Kotlin? - dictionary

I am trying to reverse a Map in Kotlin. So far, I have come up with:
mapOf("foo" to 42)
.toList()
.map { (k, v) -> v to k }
.toMap()
Is there any better way of doing this without using a middleman(middlelist)?

Since the Map consists of Entrys and it is not Iterable you can use Map#entries instead. It will be mapped to Map#entrySet to create a backed view of Set<Entry>, for example:
val reversed = map.entries.associateBy({ it.value }) { it.key }
OR use Iterable#associate, which will create additional Pairs.
val reversed = map.entries.associate{(k,v)-> v to k}
OR using Map#forEach:
val reversed = mutableMapOf<Int, String>().also {
// v-- use `forEach` here
map.forEach { (k, v) -> it.put(v, k) }
}.toMap()
// ^--- you can add `toMap()` to create an immutable Map.

Here is a simple extension function that reverse a map - without generating unneeded garbage (like pairs, intermediate data structures and unnecessary closures )
fun <K, V> Map<K, V>.reversed() = HashMap<V, K>().also { newMap ->
entries.forEach { newMap.put(it.value, it.key) }
}
note that apply is inlined, and entries.forEach is also inlined (which is not the same for Map::forEach)

In case your map is not a 1-1 mapping and you want the inversion to be a list of values:
mapOf(1 to "AAA", 2 to "BBB", 3 to "BBB").toList()
.groupBy { pair -> pair.second } // Pair<Int, String>
.mapValues { entry ->
entry.value.map { it.first } // Entry<String, List<Pair<Int, String>>
}

If you need to reverse a multimap like m: Map<K, List<V>> to a Map<V, List<K>> you can do
m
.flatMap { it.value.map { oneValue -> oneValue to it.key } }
.groupBy({ it.first }, { it.second })
.toMap()
In sequence,
mapOf('a' to listOf('b', 'c'), 'd' to listOf('b'))
gets flat mapped to a sequence like
listOf('b' to 'a', 'c' to 'a', 'b' to 'd') which gets grouped to
listOf('b' to listOf('a', 'd'), 'c' to listOf('a')) which then gets converted to a map.
This probably creates intermediate objects.

I'm still learning the ins and outs of Kotlin, but I had the same requirement and as of Kotlin 1.2 it appears that you can iterate over a Map and so map() it directly like this:
#Test
fun testThatReverseIsInverseOfMap() {
val intMap = mapOf(1 to "one", 2 to "two", 3 to "three")
val revMap = intMap.map{(k,v) -> v to k}.toMap()
assertTrue(intMap.keys.toTypedArray() contentEquals revMap.values.toTypedArray())
assertTrue(intMap.values.toTypedArray() contentEquals revMap.keys.toTypedArray())
}

This is my take on a 1:1 map
private fun <K, V> Map<K, V>.reverseOneToOneMap(): Map<V, K> {
val result = this.entries.associateBy({ it.value }) { it.key }
if (result.size != this.size) {
throw RuntimeException("Map must be 1:1")
}
return result
}

Related

Invert Map<K, List<V>> to Map<V, K>

map = mapOf((2: [3,4,5]), (7: [22,33,44]))
need to convert this to
mapOf(3:2, 4:2, 5:2, 22:7, 33:7, 44:7)
tried using associate with forEach, not sure of the syntax
There might be some nicer syntax, but this should work well enough.
fun main() {
val map = mapOf(
2 to listOf(3, 4, 5),
7 to listOf(22, 33, 44)
)
val transformedMap = map.flatMap { entry ->
entry.value.map { it to entry.key }
}.toMap()
println(transformedMap)
}
Prints
{3=2, 4=2, 5=2, 22=7, 33=7, 44=7}
Note that the toMap function states
The returned map preserves the entry iteration order of the original collection. If any of two pairs would have the same key the last one gets added to the map.
So if you have the same value in two different lists, only the last one will be included in the map.
fun main() {
val map = mapOf(
2 to listOf(3, 4, 5),
7 to listOf(22, 33, 44),
8 to listOf(3)
)
val transformedMap = map.flatMap { entry ->
entry.value.map { it to entry.key }
}.toMap()
println(transformedMap)
}
Prints {3=8, 4=2, 5=2, 22=7, 33=7, 44=7}
Zymus' answer is correct, and is also what I would probably write.
However, if this is something that will be called often, you might want to extract it to a separate function that is more efficient.
fun <K, V> Map<K, Iterable<V>>.invert(): Map<V, K> {
val newMap = mutableMapOf<V, K>()
for ((key, iterable) in this) {
for (value in iterable) {
newMap[value] = key
}
}
return newMap
}
Usage:
fun main() {
val map = mapOf((2 to listOf(3, 4, 5)), (7 to listOf(22, 33, 44)))
val inverted = map.invert()
println(inverted)
}
Output:
{3=2, 4=2, 5=2, 22=7, 33=7, 44=7}
This is functionally equivalent to
map.flatMap { (key, values) -> values.map { it to key } }.toMap()
including the behaviour where if there are duplicate values in the original input, only the last one will be preserved as a new key. However, the flatMap version creates many temporary Lists (the number of original keys + 1) and many temporary Pairs (the number of original values), whereas this iterative version creates no extra objects.

What is a more functional way of iteratively summing a list of values while capturing each intermediate result?

The code below works as expected, but the map lambda is impure. How could I refactor this to make it pure. (No need to stick to calling map, we could reduce or whatever else here, I just want it to be pure)
val entries = listOf(
Pair(LocalDate.now().minusDays(2), 1),
Pair(LocalDate.now().minusDays(1), 2),
Pair(LocalDate.now().minusDays(0), 3)
)
private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> {
var runningSum = 0.0
return entries.sortedBy { it.first }.map {
runningSum += it.second
it.copy(second = runningSum)
}.toMap()
}
val sumSchedule = buildSumSchedule(entries)
what you want here is scanReduce that's how you can use the previous item after sorting
#ExperimentalStdlibApi
private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> =
entries.sortedBy { it.first }.scanReduce { pair, acc ->
acc.copy(second = pair.second + acc.second)
}.toMap()
and from kotlin 1.4.0 runningReduce
private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> =
entries.sortedBy { it.first }.runningReduce{acc, pair ->
acc.copy(second = pair.second + acc.second)
}.toMap()

Remove null values from complex data structure in Groovy or Java

I need to remove the null key values from a complex LinkedHashMap:
Here's a simple Example:
Input
[f1:abc, f2:xyz, f3:lmn, test:null, people:[[name:James, City:Atlanta], [name:Rachel, City:null]], person:[name:James, Phone:4045555555, test:null]]
Desired Output:
[f1:abc, f2:xyz, f3:lmn, people:[[name:James, City:Atlanta], [name:Rachel]], person:[name:James, Phone:4045555555]]
I'm already half way there, I'm just stuck on removing the nulls from the List (people). Here's what I have so far:
def removeNullValues(Object map) {
map.collectEntries { k, v -> [k, v instanceof Map? removeNullValues(v) : v]}
.findAll { k, v -> v != null}
}
You can use polymorphism to select a different method depending on whether the item is a list, map, or other:
def input = [
f1:'abc',
f2:'xyz',
f3:'lmn',
test:null,
woo:[1, 2, null, 3],
people:[
[name:'James', City:'Atlanta'],
[name:'Rachel', City:null]
],
person:[name:'James', Phone:'4045555555', test:null]
]
def removeNulls(other) {
other
}
def removeNulls(List list) {
list.findResults { removeNulls(it) }
}
def removeNulls(Map map) {
map.findAll { k, v -> v != null }.collectEntries { k, v ->
[k, removeNulls(v)]
}
}
println removeNulls(input)
Which will print:
[f1:abc, f2:xyz, f3:lmn, woo:[1, 2, 3], people:[[name:James, City:Atlanta], [name:Rachel]], person:[name:James, Phone:4045555555]]

Can I convert a Kotlin KFunction1 to a KFunction0 by applying the argument?

I have a reference to a functionthat needs a parameter.
fun foo(x: Int) = 2 * x
val f: KFunction1<Int, Int> = ::foo
Is there any way to write applyArgument where
val f2: KFunction0<Int> = f1.applyArgument(42)
assertEquals("foo", f2.name)
assertEquals(84, f2())
I don't want to use a callable reference, as I need access to the name property.
hope it helps you:
fun foo(x: Int) = 2 * x
val f1 = ::foo
val f0 = { -> f1(42) }
f0() //84
KFunctions are intented to represent functions that are explicitly decleared in Kotlin code, but f2 is not declared anywhere in the code. In addition KFunction has lot of reflection properties and functions which are not relevant to the applied function f2. Therefore even if it is possible it is not recommended.
If you want to do it anyway you can simply write an applyArgument function in this way:
fun <T, R> KFunction1<T, R>.applyArgument(value: T): KFunction0<R> {
return object : KFunction<R> by this, KFunction0<R> {
override fun invoke(): R {
return this#applyArgument(value)
}
}
}
But, if what you need is to preserve the name, I would do it in a safe way. One way could be:
data class Named<out T>(val name: String, val value: T)
fun <T, R> Named<T>.map(transform: (T) -> R): Named<R> = Named(name, transform(value))
val <F : KFunction<*>> F.named: Named<F>
get() = Named(name, this)
Then use it:
fun foo(x: Int) = 2 * x
val f: Named<(Int) -> Int> = ::foo.named
val f2: Named<() -> Int> = f.map { fValue -> { fValue(42) } }
assertEquals("foo", f2.name)
assertEquals(84, f2.value())
Partial application is possible.
You may just declare a function for partial application and use it for the :: reference.
Hence, the name would not be the original function. Another approach - create your own classes/interfaces
data class MyFunction1<T, R>(val name: String, val f: (T) -> R) {
operator fun invoke(t: T) = f(t)
}
data class MyFunction0<R>(val name: String, val f: () -> R) {
operator fun invoke() = f()
}
Now define the curring:
fun MyFunction1<T, R>.curry(t: T) = MyFunction0(name){ f(t) }
(it can be a member function too)

Golang: How to create unknown (dynamic) Map length

I can create a "static" map via
type m map[int]map[int]map[int]bool
but the length of "keys" will be dynamic:
|---unknown len--|
m[1][2][3][4][2][0] = true
or
|---unk len--|
m[1][2][3][4] = true
How I can create this map in Go? Or any way exists?
Added: Hierarchical is IMPORTANT
Thanks in advance!
The map type:
A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type.
A map type must have a specific value type and a specific key type. What you want does not qualify for this: you want a map where the value is sometimes another map (of the same type), and sometimes it's a bool.
Your options:
1. With a wrapper value type
The idea here is to not use just a simple (bool) value type, but a wrapper which holds both of your potential values: both a map and the simple value (bool):
type Value struct {
Children MapType
V bool
}
type MapType map[int]*Value
var m MapType
This is basically what user3591723 suggested, so I won't detail it further.
2. With a tree
This is a variant of #1, but this way we clearly communicate it's a tree.
The cleanest way to implement your hierarchical structure would be to use a tree, where a node could look like this:
type KeyType int
type ValueType string
type Node struct {
Children map[KeyType]*Node
Value ValueType
}
This has the advantage that you may choose the value type (which is bool in your case, but you can change it to whatever type - I used string for presentation).
For easily build / manage your tree, we can add some methods to our Node type:
func (n *Node) Add(key KeyType, v ValueType) {
if n.Children == nil {
n.Children = map[KeyType]*Node{}
}
n.Children[key] = &Node{Value: v}
}
func (n *Node) Get(keys ...KeyType) *Node {
for _, key := range keys {
n = n.Children[key]
}
return n
}
func (n *Node) Set(v ValueType, keys ...KeyType) {
n = n.Get(keys...)
n.Value = v
}
And using it: 1. build a tree, 2. query some values, 3. change a value:
root := &Node{Value: "root"}
root.Add(0, "first")
root.Get(0).Add(9, "second")
root.Get(0, 9).Add(3, "third")
root.Get(0).Add(4, "fourth")
fmt.Println(root)
fmt.Println(root.Get(0, 9, 3))
fmt.Println(root.Get(0, 4))
root.Set("fourthMod", 0, 4)
fmt.Println(root.Get(0, 4))
Output (try it on the Go Playground):
&{map[0:0x104382f0] root}
&{map[] third}
&{map[] fourth}
&{map[] fourthMod}
3. With a recursive type definition
It may be surprising but it is possible to define a map type in Go which has unlimited or dynamic "depth", using a recursive definition:
type X map[int]X
It is what it says: it's a map with int keys, and values of the same type as the map itself.
The big downside of this recursive type is that it can't store any "useful" data in the value type. It can only store the "fact" whether a value is present which is identical to a bool-like information (bool type: true or false), which may be enough in rare cases, but not in most.
Let's see an example building a "tree":
var x X
x = map[int]X{}
x[0] = map[int]X{}
x[0][9] = map[int]X{}
x[0][9][3] = map[int]X{}
x[0][4] = map[int]X{}
fmt.Println(x)
Output:
map[0:map[9:map[3:map[]] 4:map[]]]
If we want to test if there is a "value" based on a series of keys, we have 2 options: either use the special v, ok := m[i] indexing (which reports if a value for the specified key exists), or test if the value is not nil, e.g. m[i] != nil.
Let's see some examples testing the above built map:
var ok bool
_, ok = x[0][9][3]
fmt.Println("x[0][9][3] exists:", ok, "; alternative way:", x[0][9][3] != nil)
_, ok = x[0][9][4]
fmt.Println("x[0][9][4] exists:", ok, "; alternative way:", x[0][9][4] != nil)
_, ok = x[0][4]
fmt.Println("x[0][4] exists:", ok, "; alternative way:", x[0][4] != nil)
_, ok = x[0][4][9][9][9]
fmt.Println("x[0][4][9][9][9] exists:", ok, "; alternative way:", x[0][4][9][9][9] != nil)
Output:
x[0][9][3] exists: true ; alternative way: true
x[0][9][4] exists: false ; alternative way: false
x[0][4] exists: true ; alternative way: true
x[0][4][9][9][9] exists: false ; alternative way: false
Try these on the Go Playground.
Note: Even though x[0][4] is the last "leaf", indexing further like x[0][4][9][9][9] will not cause a panic as a nil map can be indexed and yields the zero value of the value type (which is nil in case the value type is a map type).
Ok I had some fun playing with this a bit. Here is a much better implementation than what I did before:
type mymap map[int]*myentry
type myentry struct {
m mymap
b bool
}
func (mm mymap) get(idx ...int) *myentry {
if len(idx) == 0 {
return nil
}
entry, ok := mm[idx[0]]
if !ok {
return nil
} else if len(idx) == 1 {
return entry
}
for i := 1; i < len(idx); i++ {
if entry == nil || entry.m == nil {
return nil
}
entry = entry.m[idx[i]]
}
return entry
}
func (mm mymap) setbool(v bool, idx ...int) {
if len(idx) == 0 {
return
}
if mm[idx[0]] == nil {
mm[idx[0]] = &myentry{m: make(mymap), b: false}
} else if mm[idx[0]].m == nil {
mm[idx[0]].m = make(mymap)
}
if len(idx) == 1 {
mm[idx[0]].b = v
return
}
entry := mm[idx[0]]
for i := 1; i < len(idx); i++ {
if entry.m == nil {
entry.m = make(mymap)
entry.m[idx[i]] = &myentry{m: make(mymap), b: false}
} else if entry.m[idx[i]] == nil {
entry.m[idx[i]] = &myentry{m: make(mymap), b: false}
}
entry = entry.m[idx[i]]
}
entry.b = v
}
func (m mymap) getbool(idx ...int) bool {
if val := m.get(idx...); val != nil {
return val.b
}
return false
}
func (m mymap) getmap(idx ...int) mymap {
if val := m.get(idx...); val != nil {
return val.m
}
return nil
}
Playground link
Something like that ought to get you started
If you don't need the hierarchical map structure and just want to use keys with variable length one approach could be to simply use strings as keys and one single map.
m := make(map[string]bool)
k := fmt.Sprintf("%v_%v_%v", 1, 2, 3)
m[k] = true
fmt.Println(m[k])
You cannot do this as this sort of type is not representable in Go's type system.
You will have to redesign.
E.g. a type arbitrarilyKeyedMapwith a method lookup(vals ...int) bool.
Probably you'll need methods for setting and deletion too.

Resources