Dictionary merging in Hy - hy

If I have two dictionaries, and want to merge them with preference to the latter regarding conflicting keys, I would do in Python:
In [1]: x = {'a': 1, 'b': 2}
In [2]: y = {'b': 3, 'c': 4}
In [3]: {**x, **y}
Out[3]: {'a': 1, 'b': 3, 'c': 4}
How can I write this expression in Hy's syntax?

The dictionary-unpacking operator is unpack-mapping, or #** for short.
=> (setv x {"a" 1 "b" 2})
=> (setv y {"b" 3 "c" 4})
=> {#** x #** y}
{"a" 1 "b" 3 "c" 4}

Related

Adding arrays (from a map) to a slice of slices in Go

I have a map with arrays for keys.
I want to add all of the keys/arrays to a slice of slices.
However, I am getting unexpected results.
Code:
package main
import "fmt"
func main() {
var finalResult [][]int
set := make(map[[2]int]int)
a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
set[a], set[b], set[c] = 1, 1, 1
fmt.Println("set: ", set)
for x := range set {
fmt.Println("\nfinalResult 0: ", finalResult)
fmt.Println("x: ", x[:])
finalResult = append(finalResult, x[:])
fmt.Println("finalResult 1: ", finalResult)
}
}
Output:
set: map[[1 1]:1 [2 2]:1 [3 3]:1]
finalResult 0: []
x: [1 1]
finalResult 1: [[1 1]]
finalResult 0: [[2 2]]
x: [2 2]
finalResult 1: [[2 2] [2 2]]
finalResult 0: [[3 3] [3 3]]
x: [3 3]
finalResult 1: [[3 3] [3 3] [3 3]]
finalResult appears to be changing during the for loop?
Can someone explain what is happening and how I can work around this issue?
The problem is, that you append the x local variable to the finalResult, which is a pointer, so in every for loop, the x will point to a new array in the memory. When you add this x three times to the finalResult and print it, all the three x will be points to the same memory address. You have to copy the content where x points in every loop to a new variable and add this to the finalResult.
package main
import "fmt"
func main() {
var finalResult [][]int
set := make(map[[2]int]int)
a, b, c := [2]int{1, 1}, [2]int{2, 2}, [2]int{3, 3}
set[a], set[b], set[c] = 1, 1, 1
fmt.Println("set: ", set)
for x := range set {
fmt.Println("\nfinalResult 0: ", finalResult)
fmt.Println("x: ", x[:])
a := make([]int, 2)
copy(a, x[:])
finalResult = append(finalResult, a)
fmt.Println("finalResult 1: ", finalResult)
}
}
But be aware, that ranging over a map will be always in random order, so your final result may change on every run.

Dictionary assignment overwritten by static values in the loop

I'm trying to calculate the absolute differences between factors of two separate lists. After cross-calculation, the thought process is to save them down into a overall dictionary "kk".
kk = {}
ks = [4,5]
ks2 = [1,2,3,4]
for i in ks:
diff = {abs(i-j):j for j in ks2}
kk[i] = diff
This is what I got:
{4: {1: 4, 2: 3, 3: 2, 4: 1}, 5: {1: 4, 2: 3, 3: 2, 4: 1}}
As we can see, it is incorrect, as "kk"'s values for both keys are the same...

How to sort one array based on another array using Ruby

There are two arrays:
A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
B = [3, 4, 1, 5, 2, 6]
I want to sort B in a way that for all the elements of B that exists in A, sort the elements in the order that is in array A.
The desired sorted resulted would be
B #=> [1, 2, 3, 4, 5, 6]
I have tried to do
B = B.sort_by { |x| A.index }
but it does not work.
This question differs from the possible duplicates because it deals with presence of elements in the corresponding array and no hashes are present here.
It perfectly works:
▶ A = [1,3,2,6,4,5,7,8,9,10]
▶ B = [3,4,1,5,2,6]
▶ B.sort_by &A.method(:index)
#⇒ [1, 3, 2, 6, 4, 5]
If there could be elements in B that are not present in A, use this:
▶ B.sort_by { |e| A.index(e) || Float::INFINITY }
I would start by checking what elements from B exist in A :
B & A
and then sort it:
(B & A).sort_by { |e| A.index(e) }
First consider the case where every element of B is in A, as with the question's example:
A = [1,2,3,4,5,6,7,8,9,10]
B = [3,6,1,5,1,2,1,6]
One could write the following, which requires only a single pass through A (to construct g1) and a single pass through B.
g = A.each_with_object({}) { |n,h| h[n] = 1 }
#=> {1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>1, 7=>1, 8=>1, 9=>1, 10=>1}
B.each_with_object(g) { |n,h| h[n] += 1 }.flat_map { |k,v| [k]*(v-1) }
#=> [1, 1, 1, 2, 3, 5, 6, 6]
If there is no guarantee that all elements of B are in A, and any that are not are to be placed at the end of the sorted array, one could change the calculation of g slightly.
g = (A + (B-A)).each_with_object({}) { |n,h| h[n] = 1 }
This requires one more pass through A and through B.
Suppose, for example,
A = [2,3,4,6,7,8,9]
and B is unchanged. Then,
g = (A + (B-A)).each_with_object({}) { |n,h| h[n] = 1 }
#=> {2=>1, 3=>1, 4=>1, 6=>1, 7=>1, 8=>1, 9=>1, 1=>1, 5=>1}
B.each_with_object(g) { |n,h| h[n] += 1 }.flat_map { |k,v| [k]*(v-1) }
#=> [2, 3, 6, 6, 1, 1, 1, 5]
This solution demonstrates the value of a controversial change to hash properties that were made in Ruby v1.9: hashes would thereafter be guaranteed to maintain key-insertion order.
1 I expect one could write g = A.product([1]).to_h, but the doc Array#to_h does not guarantee that the keys in the hash returned will have the same order as they do in A.
You just missed x in A.index, so the query should be:
B = B.sort_by { |x| A.index(x) }

How can I initiate a list with a list element in julia?

I want to make a list of list in julia. It should be like this:
a = [1,"char", [1, 2, 3]]
a[3]
# ouput should be [1,2,3]
However, julia automatically does concatenation, so it ends up to be [1, "char", 1, 2, 3]
How can I do such things in julia without initiating the list with another value and then assigning a list to it like:
a = [1, "char", 3]
a[3] = [1, 2, 3]
julia> a = Any[1,"char", [1, 2, 3]]
3-element Array{Any,1}:
1
"char"
[1,2,3]
The style of array concatenation have been changes, now to concat arrays, the right syntax is: a = [1;"char"; [1, 2, 3]], so [1;"char"; [1, 2, 3]]==Any[1;"char"; [1, 2, 3]] # => true but when Julia faces [1,"char", [1, 2, 3]] by default it tries to concat possible element types.

Is there an idiomatic way to test array equality in Coffeescript?

The expression
[1, 2, 3] == [1, 2, 3]
evaluates to false in Coffeescript but is there a concise, idiomatic way to test array equality?
If you are dealing with arrays of numbers, and you know that there are no nulls or undefined values in your arrays, you can compare them as strings:
a = [1, 2, 3]
b = [1, 2, 3]
console.log "#{a}" is "#{b}" # true
console.log '' + a is '' + b # true
Notice, however, that this will break as soon as you start comparing arrays of other things that are not numbers:
a = [1, 2, 3]
b = ['1,2', 3]
console.log "#{a}" is "#{b}" # true
If you want a more robust solution, you can use Array#every:
arrayEqual = (a, b) ->
a.length is b.length and a.every (elem, i) -> elem is b[i]
console.log arrayEqual [1, 2, 3], [1, 2, 3] # true
console.log arrayEqual [1, 2, 3], [1, 2, '3'] # false
console.log arrayEqual [1, 2, 3], ['1,2', 3] # false
Notice that it's first comparing the lengths of the arrays so that arrayEqual [1], [1, 2, 3] doesn't return true.
If you don't mind introducing an Underscore.js dependency you could use some of it's utilities. It's not massively elegant, but I can't think of an easier way to do it with plain coffeescript:
a = [ 1, 2, 3 ]
b = [ 1, 2, 3 ]
equal = a.length == b.length and _.all( _.zip( a, b ), ([x,y]) -> x is y )
I wouldn't consider this idiomatic but this would be a way of doing it without adding an extra library:
a = [1, 2, 3, 4]
b = [22, 3, 4]
areEqual = true
maxIndex = Math.max(a.length, b.length)-1
for i in [0..maxIndex]
testEqual = a[i] is b[i]
areEqual = areEqual and testEqual
console.log areEqual
A cleaner approach would be using JavaScript's reduce() function. This is a bit shorter but I am not sure all browsers support reduce.
a = [1, 3, 4, 5]
b = [1, 3, 4, 5]
maxIndex = Math.max(a.length, b.length)-1
areEqual = true
[0..maxIndex].reduce (p, c, i, ar) -> areEqual = areEqual and (a[i] is b[i])
console.log "areEqual=#{areEqual}"
The following works great and requires no dependencies:
arrayEqual = (ar1, ar2) ->
JSON.stringify(ar1) is JSON.stringify(ar2)
I'm a big fan of Sugar.js. If you happen to be using that:
a = [1, 2, 3]
b = [1, 2, 3]
Object.equal(a, b)
This function returns true if arrays have same length and all values with same index have same value. It throws an error if either argument isn't an array.
isArray = Array.isArray || (subject) ->
toString.call(subject) is '[object Array]'
compareArrays = (a, b) ->
unless isArray(a) and isArray b
throw new Error '`arraysAreEqual` called with non-array'
return false if a.length isnt b.length
for valueInA, index in a
return false if b[index] isnt valueInA
true

Resources