How can I print duplicate items from an OrderedDict? - dictionary

My OrderedDict contains 5 key value pairs which result in the word, "Belle". Every letter its own key with values starting from 1 through 5, from left to right, B = 1, e = 2, etc. Printing this OrderedDict returns only 3 letters, B, l and e. Notice, it doesn't print the repeated e and ls.
In the code below, I use a for statement to print "Belle" so it can print vertically. My goal is to print the complete word "Belle" vertically, with each letter as a key with its value pair.
text6 = OrderedDict({'B':1, 'e':2, 'l':3, 'l':4, 'e':5})
for key, value in text6.items():
print(key, value)
Code above returns:
B 1
e 5
l 4
Desried output:
B 1
e 2
l 3
l 4
e 5

Asking a dict (including OrderedDict) to do what you are asking it to do is impossible. A dict of any type can only contain unique keys. All subsequently added pre-existing keys will overwrite the key and reset it's value.
In order to get the output you want to see, we can use a different data structure. In this implementation, we utilize a list which will contain a tuple for each (value, index) pair we will get by iterating through "Belle" using enumerate
list((v, i) for i, v in enumerate("Belle", 1))

Related

How to take user input and insert it into an array?

New to Julia, trying to simply ask the user to choose 5 numbers and put it into an array and print the array. My output only says pick 5 numbers with "nothing" followed underneath. I cant seem to figure out why it wont read my inputs.
function ask()
lst = []
i = 0
println("pick 5 numbers to add to a list")
while i < 5
choice = readline
choice = push!(lst, choice);
i += 1
end
end
println(ask())
You were assigning function reference to list elements rather than calling the function.
This should be:
function ask()
lst = String[]
i = 0
println("pick 5 numbers to add to a list")
while i < 5
choice = readline()
choice = push!(lst, choice);
i += 1
end
lst
end
If you want numbers rather than Strings the last line could be parse.(Int, lst) or you could add this conversion near readline
Note that if you do not plan to introduce some error checking etc. this all code could be simply written as:
println("pick 5 numbers to add to a list")
lst = [parse(Int, readline()) for _ in 1:5]

Check for equivalence of string and symbol

I have a vector of symbols a_sym of length N_sym and a vector of strings a_str of length N_str
a_sym contains symbols at each index, such as :H₅B₂O₆⁻
a_str contains strings at each index, such as H₅B₂O₆⁻
I would like to check for equivalence of a_sym and a_str to see which index the equivalence occurs in each vector.
I have tried to implement a loop to check these two vectors:
E = zeros(Int64,N_sym)
for i in 1:N_str
for ii in 1:N_sym
if a_sym[ii] == a_str[i]
E[ii] = i
end
end
end
Where E is my attempt to map equivalent indices, but my loop never detects the strings to be equivalent. How could this be remedied? (and perhaps simplified?)
For example:
a_sym = [:H₃BO₃ ,:H₄BO₄⁻ ,:Li⁺ ,:H₅B₂O₆⁻, :H₄B₃O₇⁻]
where N_sym would be 5, and:
a_str = ["O⁻","H₃BO₃","H₄BO₄⁻","H₅B₂O₆⁻","H₄B₃O₇⁻","H₃B₃O₆"]
where N_str would be 6. I require the loop to check both vectors and map the indices when there is equivalnce, for instance the index of H₃BO₃ in a_sym would be 1, and its index in a_str would be 2.
I expect a vector E = [2, 3, 0, 4, 5] which is filled with the indices of a_str, and 0 if a_str does not contain a match for a_sym
Symbols and strings are never equivalent:
julia> :a == "a"
false
So you have to convert either to the other first. I would write your function as follows using the builtin findfirst:
julia> E = [findfirst(==(String(b)), a_str) for b in a_sym]
5-element Array{Union{Nothing, Int64},1}:
2
3
nothing
4
5
(Although, as Przemislaw notes, converting the strings to symbols would likely be more efficient.)
nothing is what findfirst returns if it does not find anything. You can convert this to a default by broadcasting something:
julia> something.(E, 0)
5-element Array{Int64,1}:
2
3
0
4
5

How to implement dropWhile recursively using foldRight in Kotlin

I've been implementing higher order functions recursively with .foldRight() like any, all, and takeWhile as practice, but dropWhile has been elusive. _Collections.kt has the imperative way but I couldn't convert it to a recursive structure.
For reference, this is takeWhile
fun takeWhile(list:List<Int>, func:(Int) -> Boolean):List<Int> = list.foldRight(emptyList(),
{ next:Int, acc:List<Int> -> if (func(next)) acc.plus(next) else emptyList() })
First, let's outline the idea of the solution.
With foldRight, you can only process the items one by one from right to left, maintaining an accumulator.
The problem is, for an item at position i, the dropWhile logic makes a decision whether to include the item into the result or not based on whether there is an item at position j <= i that does not satisfy the predicate (include if yes). This means you cannot simply maintain the result items: for some items you already processed, you don't know if they should actually be included.
Example:
(we're processing the items right-to-left, so the prefix is unknown to us)
... (some unknown items) ... ... ... ... a b c d <--- (right-to-left)
predicate satisfied: T T F T
As we discover more items on the left, there are two possibilities:
We found the beginning of the sequence, and there were no items that gave F on the predicate:
(the sequence start) y z a b c d <--- (right-to-left)
predicate satisfied: T T T T F T
-------
drop
In this case, the prefix y z a b should be dropped.
We found an item that does not satisfy the predicate:
... (some unknown items) ... w z a b c d <--- (right-to-left)
predicate satisfied: F T T T F T
-------
include
Only at this point we know for sure that we need to include the items w z a b, we could not do that earlier because there could be the beginning of the sequence instead of item w, and then we should have dropped z a b.
But note that in both cases we are certain that the items c d are to be included into the result: that's because they have c with F predicate in front of them.
Given this, it becomes clear that, when processing the items right-to-left, you can maintain a separate list of items that are not certain to be included into the result and are either to be dropped or to be included when a false predicate result is encountered, together with the item that gave such false result.
My implementation:
I used a pair of two lists for the accumulator, where the first list is for the items that are certain to be included, and the second one for those which are not.
fun <T> List<T>.myDropWhile(predicate: (T) -> Boolean) =
foldRight(Pair(emptyList<T>(), emptyList<T>())) { item, (certain, uncertain) ->
if (predicate(item))
Pair(certain, uncertain + item) else
Pair(certain + uncertain + item, emptyList())
}.first.reversed()
Example:
val ints = listOf(0, 0, 0, 1, 0, 2, 3, 0, 0, 4)
println(ints.myDropWhile { it == 0 }) // [1, 0, 2, 3, 0, 0, 4]
See: runnable demo of this code with more tests.
Note: copying a read-only list by doing uncertain + item or certain + uncertain + item in each iteration gives O(n^2) worst-case time complexity, which is impractical. Using mutable data structures gives O(n) time.

Getting second and third highest value in a dictionary

dict = {'a':5 , 'b':4, 'c':3, 'd':3, 'e':1}
Second is 'b' with 4 times. Joint third are 'c' and 'd' with 3 times. As the dictionary changes over time, say, 'f' is added with a value of 3, then third will be 'c', 'd', and 'f' with 3 times.
just create a gencomp of tuple value,key and sort it. Print items
d = {'a':5 , 'b':4, 'c':3, 'd':3, 'e':1}
x = sorted(((v,k) for k,v in d.items()))
print(x[-2][1])
print(x[-3][1])
result:
b
d
(would fail if dict doesn't have at least 3 items)
Or directly with key parameter (avoids data reordering)
x = sorted(d.items(),key=(lambda i: i[1]))
print(x[-2][0])
print(x[-3][0])
result:
b
d
BTW avoid using dict as a variable.
EDIT: since there are several identical values, you may want to get the 2 second best values and the associated letters. You have to do it differently. I'd create a default list using key as value and store in a list, then sort it as done in the above code:
import collections
d = {'a':5 , 'b':4, 'c':3, 'd':3, 'e':1}
dd = collections.defaultdict(list)
for k,v in d.items():
dd[v].append(k)
x = sorted(dd.items())
print(x[-2])
print(x[-3])
result:
(4, ['b'])
(3, ['c', 'd'])

Pythonic way to iterate over a collections.Counter() instance in descending order?

In Python 2.7, I want to iterate over a collections.Counter instance in descending count order.
>>> import collections
>>> c = collections.Counter()
>>> c['a'] = 1
>>> c['b'] = 999
>>> c
Counter({'b': 999, 'a': 1})
>>> for x in c:
print x
a
b
In the example above, it appears that the elements are iterated in the order they were added to the Counter instance.
I'd like to iterate over the list from highest to lowest. I see that the string representation of Counter does this, just wondering if there's a recommended way to do it.
You can iterate over c.most_common() to get the items in the desired order. See also the documentation of Counter.most_common().
Example:
>>> c = collections.Counter(a=1, b=999)
>>> c.most_common()
[('b', 999), ('a', 1)]
Here is the example to iterate the Counter in Python collections:
>>>def counterIterator():
... import collections
... counter = collections.Counter()
... counter.update(('u1','u1'))
... counter.update(('u2','u2'))
... counter.update(('u2','u1'))
... for ele in counter:
... print(ele,counter[ele])
>>>counterIterator()
u1 3
u2 3
Your problem was solved for just returning descending order but here is how to do it generically. In case someone else comes here from Google here is how I had to solve it. Basically what you have above returns the keys for the dictionary inside collections.Counter(). To get the values you just need to pass the key back to the dictionary like so:
for x in c:
key = x
value = c[key]
I had a more specific problem where I had word counts and wanted to filter out the low frequency ones. The trick here is to make a copy of the collections.Counter() or you will get "RuntimeError: dictionary changed size during iteration" when you try to remove them from the dictionary.
for word in words.copy():
# remove small instance words
if words[word] <= 3:
del words[word]

Resources