Tcl dict create makes weird dictionary - dictionary

set table [dict create cells state bits state]
set data [dict create 1 "s" 1 "f"]
puts $table
puts $data
puts out:
cells state bits state
1 f
This is quite weird! why doesn't dict create make a full dictionary on 1 s 1 f ?
thanks!
ps documentation says:
dict create ?key value ...?
Return a new dictionary that contains each
of the key/value mappings listed as arguments (keys and values
alternating, with each key being followed by its associated value.)
https://www.tcl.tk/man/tcl/TclCmd/dict.htm#M6
Post Post Script:
I found that putting any two keys that are the same does the same thing such as:
puts [dict create 2 "s" 2 "f"]
2 f

If you enter different values for the same key (key = 1 in the first case, key = 2 in the second), an associative container like the Tcl dict will keep only one of those values.
You can still have a data structure that has multiple equal keys, just don't use dict create, which enforces the unique-key trait (that's AFAIK the only reason to initialize dictionaries with dict create):
% set data {1 s 1 f}
1 s 1 f
% dict get $data 1
f
% set data [dict create 1 s 1 f]
1 f
% dict get $data 1
f
Dictionary-handling commands will deal with this structure as if it had only one each of the keys. Dictionary-mutating commands will not preserve the multiple equal keys of the original structure.

Related

How can I choose to show only unequal data result and minus or blind equal data result?

Here's my robot code
There are 22 records on both tables but only 1 record has an unequal data I would like to show that result and minus or blind an equal data result.
connect to database using custom params cx_Oracle ${DB_CONNECT_STRING}
#{queryResultsA}= Query Select count (*) from QA_USER.SealTest_Security_A order by SECURITY_ID
Log ${queryResultsA}
#{queryResultsB}= Query Select count (*) from QA_USER.SealTest_Security_B order by SECURITY_ID
Log ${queryResultsB}
should not contain match ${queryResultsB} ${queryResultsA}
Using For Loop
# Assuming your table has values like this
#{queryResultsA}= Create List a b c d e
#{queryResultsB}= Create List a z c d e
${Length}= Get Length ${queryResultsA}
${count}= Set Variable
:FOR ${count} IN RANGE ${Length}
\ Run Keyword If '#{queryResultsA}[${count}]'!='#{queryResultsB}[${count}]' Log To Console #{queryResultsA}[${count}] #{queryResultsB}[${count}]
OUTPUT
b z
Using SET
${z} = Evaluate (set(${queryResultsA}) - set(${queryResultsB}))
Log ${z}
OUTPUT
b
Note the difference here Set B is subtracted from Set A so whatever not matched in set A will be the output.

The number of occurences of elements in a vector [JULIA]

I have a vector of 2500 values composed of repeated values and NaN values. I want to remove all the NaN values and compute the number of occurrences of each other value.
y
2500-element Array{Int64,1}:
8
43
NaN
46
NaN
8
8
3
46
NaN
For example:
the number of occurences of 8 is 3
the number of occurences of 46 is 2
the number of occurences of 43 is 1.
To remove the NaN values you can use the filter function. From the Julia docs:
filter(function, collection)
Return a copy of collection, removing elements for which function is false.
x = filter(y->!isnan(y),y)
filter!(y->!isnan(y),y)
Thus, we create as our function the conditional !isnan(y) and use it to filter the array y (note, we could also have written filter(z->!isnan(z),y) using z or any other variable we chose, since the first argument of filter is just defining an inline function). Note, we can either then save this as a new object or use the modify in place version, signaled by the ! in order to simply modify the existing object y
Then, either before or after this, depending on whether we want to include the NaNs in our count, we can use the countmap() function from StatsBase. From the Julia docs:
countmap(x)
Return a dictionary mapping each unique value in x to its number of
occurrences.
using StatsBase
a = countmap(y)
you can then access specific elements of this dictionary, e.g. a[-1] will tell you how many occurrences there are of -1
Or, if you wanted to then convert that dictionary to an Array, you could use:
b = hcat([[key, val] for (key, val) in a]...)'
Note: Thanks to #JeffBezanon for comments on correct method for filtering NaN values.
y=rand(1:10,20)
u=unique(y)
d=Dict([(i,count(x->x==i,y)) for i in u])
println("count for 10 is $(d[10])")
countmap is the best solution I've seen so far, but here's a written out version, which is only slightly slower. It only passes over the array once, so if you have many unique values, it is very efficient:
function countmemb1(y)
d = Dict{Int, Int}()
for val in y
if isnan(val)
continue
end
if val in keys(d)
d[val] += 1
else
d[val] = 1
end
end
return d
end
The solution in the accepted answer can be a bit faster if there are a very small number of unique values, but otherwise scales poorly.
Edit: Because I just couldn't leave well enough alone, here's a version that is more generic and also faster (countmap doesn't accept strings, sets or tuples, for example):
function countmemb(itr)
d = Dict{eltype(itr), Int}()
for val in itr
if isa(val, Number) && isnan(val)
continue
end
d[val] = get(d, val, 0) + 1
end
return d
end

String SHA1 in Julia

I have an ordered set of points (x,y pairs) I would like to use as a key in a dictionary.
My original approach in ruby was to get a string representation of the points and then SHA1 the results.
What would be the best way to accomplish this in Julia?
Edit:
The key that I want to create is the set of points, not the individual points within the set.
I have a process that creates a set of unique integer points and I want to see if I have encountered this particular set of points before. I also want to store some information about this particular set of points. For example how many times have I seen this configuration.
The length of the set of points varies between 20 and 180ish.
With a SHA1 hash of the string representation of these points I know that my key is going to be 40 characters long regardless of the length of the points.
In effect I'm using SHA1 to compress my key to keep the size of my dictionary as small as I can. I would like this dictionary to grow to a fairly large size.
You can just use the points them directly as keys of a dictionary, e.g.
points = [(rand(),rand()) for i in 1:100]
a_dict = [p => rand(1:10000) for p in points]
#show points[1]
#show a_dict[points[1]]
produces
points[1] => (0.4374267407775083,0.32232663537074036)
a_dict[points[1]] => 4102
EDIT: The question is asking about lists of points rather than single pairs. Its hard to tell from your question, but if you wanted to throw out the lists of points, then I'd just use the hash function, which is what a dictionary uses:
julia> x = [(rand(),rand()) for i in 1:100];
julia> y = copy(x);
julia> z = [(rand(),rand()) for i in 1:100];
julia> hash(x)
0x2dd258e3af0ec93a
julia> hash(y)
0x2dd258e3af0ec93a
julia> hash(z)
0x6449b750e42e6bc6
julia> some_dict = [hash(x) => 1, hash(z) => 1]
Dict{Uint64,Int64} with 2 entries:
0x6449b750e42e6bc6 => 1
0x2dd258e3af0ec93a => 1
julia> if hash(y) in keys(some_dict)
some_dict[hash(y)] += 1
else
some_dict[hash(y)] = 1
end
julia> some_dict
Dict{Uint64,Int64} with 2 entries:
0x6449b750e42e6bc6 => 1
0x2dd258e3af0ec93a => 2
If you actually need to retrieve what the sets of points are though, which seems likely, then you can just use a dictionary directly with the set of points as the key, i.e.
julia> other_dict = [x=>1,z=>1]
Dict{Array{(Float64,Float64),1},Int64} with 2 entries:
[(0.6453074757765922,0.0958215… => 1
[(0.5283378708792779,0.8418390… => 1
julia> other_dict[y] += 1
2
julia> other_dict
Dict{Array{(Float64,Float64),1},Int64} with 2 entries:
[(0.6453074757765922,0.0958215… => 1
[(0.5283378708792779,0.8418390… => 2
This (using mutable keys) is perfectly fine in Julia (although bad things will happen if you change the keys of dictionary once they've been added, of course).

Make 1 key from 2 vigenere keys

I have this school assignment about Vigenere code.
I've got 2 keys: AB and XYZ. A text is encrypted twice with these keys.
The questions are:
How to make 1 key out of those 2?
How to make 1 key when there are 3 keys?
Choose the length of the combined key as the least common multiple of the key lengths.
Repeat each key until it fills the combined key
Add all the repeated keys.
For example with AB and XYZ assuming A=0:
The lengths are 2 and 3, the common multiple is 6.
AB AB AB and XYZ XYZ
A+X, B+Y, A+Z, B+X, A+Y, B+Z = XZZYYA
This algorithm works with any number of keys.
#CodesInChaos answer is great, but let's add some math:
|C| = gcd(|A|, |B|)
# gcd: greatest common divisor.
Also notice that you can compute the value of the combined key:
Let's define the keys as:
A=(a_0,a_1,…,a_i)
B=(b_0,b_1,…,b_j)
Then the value of the combined key is:
C={c_i=a_(i%|A|)+b_(i%|B|) | 0≤i≤lcd(|A|,|B|)}
And can be generalized to each number of keys:
C={c_i=a_(i%|A|)+b_(i%|B|)+...+z_(i%|Z|) | 0≤i≤lcd(|A|,|B|,...,|Z|)}

Data manipulation using a script

I have data in the following format :
Key1:Value1 Key2:Value2 Key3:Value3
A
B
C
D
Key1:Value4 Key2:Value5 Key3:Value6
A1
B1
C1
Key1..
and so on. The number of keys is always three, and in this same order. No extra lines between the values A,B,C,D in the original data set.
I want to get output in the format
Value3, A B C D
Value6, A1 B1 C1
.
.
.
Any thoughts on a script I might be able to use to get this done
Regular expressions can help you but depends on what type of values those are in general you can write it up to match for Key3: [Pattern to match value] and graph that and then all successive lines before the next Key1 can be grabbed manually with a for loop and stop until you get to new key line and repeat for each section.
Pseudocode:
current_key = ""
while !EOF:
line = next_line()
if line has regular expression for "Key3: Value":
process for Value
current_key = Value
else
process line as a regular ABCD value and print or whatever
There isn't much error checking but hopefully that helps get you going.

Resources