Kotlin convert List with nullables to HashMap without nullables - collections

I have incoming param List<Somedata>.Somedata class contains id field.
My goal is to make HashMap<Somedata.id, Somedata> from this list.
Is next approach correct or there is a better/safer way to do that?
list
.filter { it.id != null }
.associateTo(HashMap(), {it.id!! to it})
Actually, I cannot understand, why should I use !! keyword in associateTo method, when above I filtered it with non-null values only.
Or maybe there is a good way to perform this with ?. or ?.let keywords?

You can do:
list.mapNotNull { e -> e.id?.let { it to e } }.toMap()
Breakdown:
The call to .let with the ?. safe call operator will make the result null if the element is null.
So the lambda passed to mapNotNull is of type (Somedata) -> Pair<IdType, Somedata>.
mapNotNull discards the null pairs, and toMap turns the resulting List<Pair<IdType, Somedata>> into a Map<IdType, Somedata>.
If you want to avoid the creation of an intermediate list to hold the pairs, you can turn the list into a lazy Sequence from the start:
list.asSequence().mapNotNull { e -> e.id?.let { it to e } }.toMap()
Alternatively, since you asked:
why should I use !! keyword in associateTo method, when above I filtered it with non-null values only.
this is because the list is still of type List<Somedata> - this says nothing about the nullability of the field itself. The compiler does not know that the id fields are still not null, by the time your associateTo call is executed.

Related

Swiftui: how do you assign the value in a "String?" object to a "String" object?

Swiftui dictionaries have the feature that the value returned by using key access is always of type "optional". For example, a dictionary that has type String keys and type String values is tricky to access because each returned value is of type optional.
An obvious need is to assign x=myDictionary[key] where you are trying to get the String of the dictionary "value" into the String variable x.
Well this is tricky because the String value is always returned as an Optional String, usually identified as type String?.
So how is it possible to convert the String?-type value returned by the dictionary access into a plain String-type that can be assigned to a plain String-type variable?
I guess the problem is that there is no way to know for sure that there exists a dictionary value for the key. The key used to access the dictionary could be anything so somehow you have to deal with that.
As described in #jnpdx answer to this SO question (How do you assign a String?-type object to a String-type variable?), there are at least three ways to convert a String? to a String:
import SwiftUI
var x: Double? = 6.0
var a = 2.0
if x != nil {
a = x!
}
if let b = x {
a = x!
}
a = x ?? 0.0
Two key concepts:
Check the optional to see if it is nil
if the optional is not equal to nil, then go ahead
In the first method above, "if x != nil" explicitly checks to make sure x is not nil be fore the closure is executed.
In the second method above, "if let a = b" will execute the closure as long as b is not equal to nil.
In the third method above, the "nil-coalescing" operator ?? is employed. If x=nil, then the default value after ?? is assigned to a.
The above code will run in a playground.
Besides the three methods above, there is at least one other method using "guard let" but I am uncertain of the syntax.
I believe that the three above methods also apply to variables other than String? and String.

Initialize pointer array - cannot make type *[]type

Its a simple code, saving car type objects into a car type array. I am trying to use pointer here to pass array reference.
There are 2 problems:
1 - I can't initialize it as empty array. When I use make, it says:
cannot make type *[]car
2 - If I don't use make, runtime error occurs:
panic: runtime error: invalid memory address or nil pointer dereference
Code:
import "fmt"
type car struct {
plate string
color string
}
func main() {
var _cars *[]car // list of cars
_cars = make(*[]car, 4) // initialize empty cars list
saveCar(_cars, car{"ABC-123", "Black"})
saveCar(_cars, car{"ABC-456", "Black"})
saveCar(_cars, car{"ABC-789", "Black"})
fmt.Println(_cars)
}
func saveCar(_cars_list *[]car, _car car) int {
for index, current := range *_cars_list {
// if empty place found, save car
if (car{}) == current {
// save car
(*_cars_list)[index] = _car
// return the saved index
return index
}
}
return -1
}
Changing this would make your code work:
tCars := make([]car, 4)
_cars = &tCars
1 - cannot make type *[]car
You observe it because make creates slice, map or chan. In the example you gave you tried to create pointer to a slice which is none of the typed make works with.
2 - If I don't use make, runtime error occurs:
that's another problem - you have type "pointer to a slice of car", not "a slice of car". And in general you need to initialize pointer types before using.
Overall there is no need to use pointer to a slice rather than plain slice in your case, because you don't use append, to there is no chance for reallocation of backed storage.
However, in a real world scenario, when you don't know amount of car instances you are going to add, is much better to use append instead of iterating through slice till the last non-initialized value.
summary:
to make your program work change *[]car to []car everywhere (example https://play.golang.org/p/lpCtvXqG6UY)
another (and probably better) way is to use append instead of saveCar (don't forget to use returned value in case of happened re-allocation, example: https://play.golang.org/p/L8V10tSb-IJ)

Find a specific tuple by key in an Erlang list (eJabberd HTTP Header)

I am just getting started with eJabberd and am writing a custom module with HTTP access.
I have the request going through, but am now trying to retrieve a custom header and that's where I'm having problems.
I've used the Request record to get the request_headers list and can see that it contains all of the headers I need (although the one I'm after is a binary string on both the key and value for some reason...) as follows:
[
{ 'Content-Length', <<"100">> },
{ <<"X-Custom-Header">>, <<"CustomValue">> },
{ 'Host', <<"127.0.0.1:5280">> },
{ 'Content-Type', <<"application/json">> },
{ 'User-Agent', <<"Fiddler">> }
]
This is also my first foray into functional programming, so from procedural perspective, I would loop through the list and check if the key is the one that I'm looking for and return the value.
To this end, I've created a function as:
find_header(HeaderKey, Headers) ->
lists:foreach(
fun(H) ->
if
H = {HeaderKey, Value} -> H;
true -> false
end
end,
Headers).
With this I get the error:
illegal guard expression
I'm not even sure I'm going about this the right way so am looking for some advice as to how to handle this sort of scenario in Erlang (and possibly in functional languages in general).
Thanks in advance for any help and advice!
PhilHalf
The List that you have mentioned is called a "Property list", which is an ordinary list containing entries in the form of either tuples, whose first elements are keys used for lookup and insertion or atoms, which work as shorthand for tuples {Atom, true}.
To get a value of key, you may do the following:
proplists:get_value(Key,List).
for Example to get the Content Length:
7> List=[{'Content-Length',<<"100">>},
{<<"X-Custom-Header">>,<<"CustomValue">>},
{'Host',<<"127.0.0.1:5280">>},
{'Content-Type',<<"application/json">>},
{'User-Agent',<<"Fiddler">>}].
7> proplists:get_value('Content-Type',List).
<<"application/json">>
You can use the function lists:keyfind/3:
> {_, Value} = lists:keyfind('Content-Length', 1, Headers).
{'Content-Length',<<"100">>}
> Value.
<<"100">>
The 1 in the second argument tells the function what tuple element to compare. If, for example, you wanted to know what key corresponds to a value you already know, you'd use 2 instead:
> {Key, _} = lists:keyfind(<<"100">>, 2, Headers).
{'Content-Length',<<"100">>}
> Key.
'Content-Length'
As for how to implement this in Erlang, you'd write a recursive function.
Imagine that you're looking at the first element of the list, trying to figure out if this is the entry you're looking for. There are three possibilities:
The list is empty, so there is nothing to compare.
The first entry matches. Return it and ignore the rest of the list.
The first entry doesn't match. Therefore, the result of looking for this key in this list is the same as the result of looking for it in the remaining elements: we recurse.
find_header(_HeaderKey, []) ->
not_found;
find_header(HeaderKey, [{HeaderKey, Value} | _Rest]) ->
{ok, Value};
find_header(HeaderKey, [{_Key, _Value} | Rest]) ->
find_header(HeaderKey, Rest).
Hope this helps.

If exists in R using this

I want to see if a variable exists - i.e. that I have created in.
if(exists(this.mydict))
{ //append my dict
}else
{
// initialize dict
}
Trouble is this fails on
Error in exists(this.mydict)
What am I doing wrong?
How can I extend the exists function to work with the following:
Any ideas how I would extend to this to looking at seeing whether a nested dictionary would also exist. I.e. for example: if(exists("mylists[[index]]['TSI']")), where the mylists object is a dictionary look up that also wants to contain a nested dictionary.
exists() function takes a character argument with the variable name:
if(exists("this.mydict")){
# you can use this.mydict here
}else{
# initialize this.mydict
# e.g. this.mydict <- "some value here"
}

Passing custom slice types by reference

I'm having trouble wrapping my head around how pointers, slices, and interfaces interact in Go. This is what I currently have coded up:
type Loader interface {
Load(string, string)
}
type Foo struct {
a, b string
}
type FooList []Foo
func (l FooList) Load(a, b string) {
l = append(l, Foo{a, b})
// l contains 1 Foo here
}
func Load(list Loader) {
list.Load("1", "2")
// list is still nil here
}
Given this setup, I then try to do the following:
var list FooList
Load(list)
fmt.Println(list)
However, list is always nil here. My FooList.Load function does add an element to the l slice, but that's as far as it gets. The list in Load continues to be nil. I think I should be able to just pass the reference to my slice around and have things append to it. I'm obviously missing something on how to get it to work though.
(Code in http://play.golang.org/p/uuRKjtxs9D)
If you intend your method to make changes, you probably want to use a pointer receiver.
// We also define a method Load on a FooList pointer receiver.
func (l *FooList) Load(a, b string) {
*l = append(*l, Foo{a, b})
}
This has a consequence, though, that a FooList value won't itself satisfy the Loader interface.
var list FooList
Load(list) // You should see a compiler error at this point.
A pointer to a FooList value, though, will satisfy the Loader interface.
var list FooList
Load(&list)
Complete code below:
package main
import "fmt"
/////////////////////////////
type Loader interface {
Load(string, string)
}
func Load(list Loader) {
list.Load("1", "2")
}
/////////////////////////////
type Foo struct {
a, b string
}
// We define a FooList to be a slice of Foo.
type FooList []Foo
// We also define a method Load on a FooList pointer receiver.
func (l *FooList) Load(a, b string) {
*l = append(*l, Foo{a, b})
}
// Given that we've defined the method with a pointer receiver, then a plain
// old FooList won't satisfy the Loader interface... but a FooList pointer will.
func main() {
var list FooList
Load(&list)
fmt.Println(list)
}
I'm going to simplify the problem so it's easier to understand. What is being done there is very similar to this, which also does not work (you can run it here):
type myInt int
func (a myInt) increment() { a = a + 1 }
func increment(b myInt) { b.increment() }
func main() {
var c myInt = 42
increment(c)
fmt.Println(c) // => 42
}
The reason why this does not work is because Go passes parameters by value, as the documentation describes:
In a function call, the function value and arguments are evaluated in the usual
order. After they are evaluated, the parameters of the call are passed by value
to the function and the called function begins execution.
In practice, this means that each of a, b, and c in the example above are pointing to different int variables, with a and b being copies of the initial c value.
To fix it, we must use pointers so that we can refer to the same area of memory (runnable here):
type myInt int
func (a *myInt) increment() { *a = *a + 1 }
func increment(b *myInt) { b.increment() }
func main() {
var c myInt = 42
increment(&c)
fmt.Println(c) // => 43
}
Now a and b are both pointers that contain the address of variable c, allowing their respective logic to change the original value. Note that the documented behavior still holds here: a and b are still copies of the original value, but the original value provided as a parameter to the increment function is the address of c.
The case for slices is no different than this. They are references, but the reference itself is provided as a parameter by value, so if you change the reference, the call site will not observe the change since they are different variables.
There's also a different way to make it work, though: implementing an API that resembles that of the standard append function. Again using the simpler example, we might implement increment without mutating the original value, and without using a pointer, by returning the changed value instead:
func increment(i int) int { return i+1 }
You can see that technique used in a number of places in the standard library, such as the strconv.AppendInt function.
It's worth keeping a mental model of how Go's data structures are implemented. That usually makes it easier to reason about behaviour like this.
http://research.swtch.com/godata is a good introduction to the high-level view.
Go is pass-by-value. This is true for both parameters and receivers. If you need to assign to the slice value, you need to use a pointer.
Then I read somewhere that you shouldn't pass pointers to slices since
they are already references
This is not entirely true, and is missing part of the story.
When we say something is a "reference type", including a map type, a channel type, etc., we mean that it is actually a pointer to an internal data structure. For example, you can think of a map type as basically defined as:
// pseudocode
type map *SomeInternalMapStructure
So to modify the "contents" of the associative array, you don't need to assign to a map variable; you can pass a map variable by value and that function can change the contents of the associative array pointed to by the map variable, and it will be visible to the caller. This makes sense when you realize it's a pointer to some internal data structure. You would only assign to a map variable if you want to change which internal associative array you want it to point to.
However, a slice is more complicated. It is a pointer (to an internal array), plus the length and capacity, two integers. So basically, you can think of it as:
// pseudocode
type slice struct {
underlyingArray uintptr
length int
capacity int
}
So it's not "just" a pointer. It is a pointer with respect to the underlying array. But the length and capacity are "value" parts of the slice type.
So if you just need to change an element of the slice, then yes, it acts like a reference type, in that you can pass the slice by value and have the function change an element and it's visible to the caller.
However, when you append() (which is what you're doing in the question), it's different. First, appending affects the length of the slice, and length is one of the direct parts of the slice, not behind a pointer. Second, appending may produce a different underlying array (if the capacity of the original underlying array is not enough, it allocates a new one); thus the array pointer part of the slice might also be changed. Thus it is necessary to change the slice value. (This is why append() returns something.) In this sense, it cannot be regarded as a reference type, because we are not just "changing what it points to"; we are changing the slice directly.

Resources