How to convert dictionary of indices to list of keys? - python

Say you have a dictionary listing the indices where each unique value appear. For example say you alphabet is just a and b then this dictionary will look something like: d = {'a': [1, 2, 6], 'b': [3, 7]}. I would like to convert it to the raw list which shows at the right index the right value, such that in the last example, l = ['a','a','b',None,None,'a',b']. I prefer an easy small solution rather than one which has tedious for loops. Thank!

Obviously doing this without for loops is a terrible idea, because the easiest way is (it's not perfect, but it does the job):
r = {}
for key, value in d.items():
for element in value:
r[element] = key
l = [r.get(i) for i in xrange(1, max(r) + 1)]
But if you REALLY want to know how to do this without any for then have a look:
m = {}
i = 0
d_keys = d.keys()
max_value = 0
while i < len(d):
d_i = d[d_keys[i]]
j = 0
while j < len(d_i):
d_i_j = d_i[j]
if max_value < d_i_j:
max_value = d_i_j
m[d_i_j] = d_keys[i]
j += 1
i += 1
l = []
i = 1
while i <= max_value:
l.append(m.get(i))
i += 1
It's quite easy, isn't it?

I don't know why you need that, but here is a dirty answer, without loops.
d = {'a': [1, 2, 6], 'b': [3, 7]}
map(lambda x: x[0] if x else None, map(lambda x: filter(lambda l: x in d[l], d), range(1, max(reduce(lambda x, y: x+y, map(lambda x:d[x], d)))+1)))

d.keys()
keys()
Return a copy of the dictionary’s list of keys. See the note for dict.items()
from Python Docs

Related

How can I iterate over a list of integers, and reference the largest key in my dictionary (all integers) so that it is smaller than current value?

I have a dictionary with positive integers as keys, the values don't matter for my question.
Separately, I am iterating through a list of integers, and I want to reference the largest key in my dictionary, that is smaller than the current integer that I am iterating over in my list (if it exists!).
For example:
from collections import defaultdict
def Loep(obstacles):
my_dict = defaultdict(int)
output = []
for i in range(len(obstacles)):
if max(j for j in my_dict.keys() if j<= obstacles[i]):
temp = max(j for j in my_dict.keys() if j<= obstacles[i])
my_dict[obstacles[i]] = temp + 1
output.append(my_dict[obstacles[i]])
else:
my_dict[obstacles[i]] = 1
output.append(my_dict[obstacles[i]])
print(Loep([3,1,5,6,4,2]))
I am getting an error for the 'if' statement above- I believe it is because I have one too many arguments in max(), any ideas how to amend the code?
The error is: ValueError: max() arg is an empty sequence
I've tried separating it, but I can't quite do it.
Something like this:
from collections import defaultdict
def Loep(obstacles):
my_dict = defaultdict(int)
my_dict.update({
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
})
output = []
for obstacle in obstacles:
keys = [j for j in my_dict.keys() if j <= obstacle]
if keys:
# there is at least one qualifying key
key = max(keys)
my_dict[obstacle] = key + 1
output.append(my_dict[obstacle])
else:
my_dict[obstacle] = 1
output.append(my_dict[obstacle])
return output
print(Loep([3, 1, 5, 6, 4, 2]))
In response to your comment about doing it in one line.. yes, you could condense it like so:
for obstacle in obstacles:
key = max([None]+[j for j in my_dict.keys() if j <= obstacle])
if key is not None:
# etc
.. and definitely there are other ways to do it.. using filter.. or other ways.. but end of the day you are trying to not just get the max, but to get the max lower than a specific value. Unless you're working with a very large amount of data, or in need of extreme speed.. that this is the easiest way.
Try this. Is it what you want?
from collections import defaultdict
def Loep(obstacles):
my_dict = defaultdict(int)
output = []
for i in range(len(obstacles)):
founds = [j for j in my_dict.keys() if j <= obstacles[i]]
if founds:
max_val = max(founds)
my_dict[obstacles[i]] = max_val + 1
else:
my_dict[obstacles[i]] = 1
output.append(my_dict[obstacles[i]])
return output
print(Loep([3, 1, 5, 6, 4, 2]))

I want to write a function that takes a list and returns a count of total number of duplicate elements in the list

I have tried this, for some unknown reason when it prints h, it prints None, so i thought if it counts the number of None printed then divided by 2 it will give the number of duplicates, but i cant use function count here
a= [1,4,"hii",2,4,"hello","hii"]
def duplicate(L):
li=[]
lii=[]
h=""
for i in L:
y= L.count(i)
if y>1:
h=y
print h
print h.count(None)
duplicate(a)
Use the Counter container:
from collections import Counter
c = Counter(['a', 'b', 'a'])
c is now a dictionary with the data: Counter({'a': 2, 'b': 1})
If you want to get a list with all duplicated elements (with no repetition), you can do as follows:
duplicates = filter(lambda k: c[k] > 1, c.iterkeys())
If you want to only count the duplicates, you can then just set
duplicates_len = len(duplicates)
You can use a set to get the count of unique elements, and then compare the sizes - something like that:
def duplicates(l):
uniques = set(l)
return len(l) - len(uniques)
i found an answer which is
a= [1,4,"hii",2,4,"hello",7,"hii"]
def duplicate(L):
li=[]
for i in L:
y= L.count(i)
if y>1:
li.append(i)
print len(li)/2
duplicate(a)
the answer by egualo is much better, but here is another way using a dictionary.
def find_duplicates(arr):
duplicates = {}
duplicate_elements = []
for element in arr:
if element not in duplicates:
duplicates[element] = False
else:
if duplicates[element] == False:
duplicate_elements.append(element)
duplicates[element] = True
return duplicate_elements
It's pretty simple and doesn't go through the lists twice which is kind of nice.
>> test = [1,2,3,1,1,2,2,4]
>> find_duplicates(test)
[1, 2]

OrderedDict Changing Order after Double Iterator Loop

I set up an OrderedDict and perform dictionary comprehensions with different grammars, which I have simplified to a function dictcomp(fn, dictionary, key_or_value)::
x = OrderedDict(self._Median_Colors)
x = self.dictcomp(hex2color, x, 'v')
x = self.dictcomp(rgb_to_hsv, x, 'v_tuple')
At this point I am able to sort the dictionary:
x = self.dictcomp(self.sort_by_hue, x, 'v')
Everything seems to check out so far:
print x
Now I need to rename keys, so I will create a new ordered dictionary:
color_indexes = list(xrange(0, len(x.keys())))
print color_indexes
newkeys = [self.rename(color_index) for color_index in color_indexes]
print x.values()
vi = iter(x.values())
x = OrderedDict.fromkeys(newkeys);
I had no idea how to fill in the old values immediately, so I did this:
ki = iter(x.keys())
for k, v in zip(ki, vi):
#print "k:", k
print v
x[k] = tuple(v)
Checks out fine:
print x.items()
Here comes trouble:
x = self.dictcomp(hsv_to_rgb, x, 'v_tuple')
print x.items()
where dictcomp does this:
dictionary = {k: fn(*v) for k, v in dictionary.items()}
where fn=hsv_to_rgb, dictionary=x
Now, I have:
[('Blue', (0.9764705882352941, 0.5529411764705883, 0.0)), ....
instead of the expected:
[('Red', (0.4745098039215686, 0.7372549019607844, 0.23137254901960794)), ....
The keys are the same, but the values have changed. I am guessing that the insertion order was somehow affected. How did this happen and how can I keep the order of keys in the dictionary?
The problem is because of
for i, j in zip([4, 5, 6], [1, 2, 3]):
print i
print j
Results in the column:
4 1 5 2 6 3
It turns out that zip acts as a zipper if using two iterators.
The fix is to get the keyword-value as an iterable tuple:
for i in zip([4, 5, 6], [1, 2, 3]):
print i
Returns
(4, 1)
(5, 2)
(6, 3)

Dictionary deletion of values going out of index

I have a dictionary
k = {'a':[7,2,3],'b':[7,2,7], 'c': [8,9,10]}
where is each val is a list. I want to delete the ith term(depending on condition) in a val without going out of range. this is code for it
for i in range(len(k['a'])):
if k['a'][i] == k['b'][i]:
pass
else:
for key in k:
del [k[key][i]]
This would work return a dictionary equivalent to this
{'a':[7,2],'b':[7,2], 'c': [8,9]}
However if the dictionary was this
k = {'a':[6,2,3],'b':[7,2,7], 'c': [8,9,10]}
I would get this Error
list index out of range
How I delete key vals so I don't get this error?
The issue is that when you delete one item from each array, the size of these arrays decreases by one. Thus, the main loop becomes one iteration too long.
An illustration of the problem:
>>> a = [1, 2, 3]
>>> i = 2
>>> a[i]
3
>>> len(a)
3
>>> del [a[1]]
>>> a
[1, 3]
>>> len(a)
2
>>> a[i] # used to work
IndexError: list index out of range
In order for the index and the loop duration to work out you need to do something like this:
i = 0
while i < len(k['a']):
if k['a'][i] == k['b'][i]:
i += 1
else:
for key in k:
del [k[key][i]]

Get a unique list of items that occur more than once in a list

I have a list of items:
mylist = ['A','A','B','C','D','E','D']
I want to return a unique list of items that appear more than once in mylist, so that my desired output would be:
[A,D]
Not sure how to even being this, but my though process is to first append a count of each item, then remove anything equal to 1. Then dedupe, but this seems like a really roundabout, inefficient way to do it, so I am looking for advice.
You can use collections.Counter to do what you have described easily:
from collections import Counter
mylist = ['A','A','B','C','D','E','D']
cnt = Counter(mylist)
print [k for k, v in cnt.iteritems() if v > 1]
# ['A', 'D']
>>> mylist = ['A','A','B','C','D','E','D']
>>> set([i for i in mylist if mylist.count(i)>1])
set(['A', 'D'])
import collections
cc = collections.Counter(mylist) # Counter({'A': 2, 'D': 2, 'C': 1, 'B': 1, 'E': 1})
cc.subtract(cc.keys()) # Counter({'A': 1, 'D': 1, 'C': 0, 'B': 0, 'E': 0})
cc += collections.Counter() # remove zeros (trick from the docs)
print cc.keys() # ['A', 'D']
Try some thing like this:
a = ['A','A','B','C','D','E','D']
import collections
print [x for x, y in collections.Counter(a).items() if y > 1]
['A', 'D']
Reference: How to find duplicate elements in array using for loop in Python?
OR
def list_has_duplicate_items( mylist ):
return len(mylist) > len(set(mylist))
def get_duplicate_items( mylist ):
return [item for item in set(mylist) if mylist.count(item) > 1]
mylist = [ 'oranges' , 'apples' , 'oranges' , 'grapes' ]
print 'List: ' , mylist
print 'Does list have duplicate item(s)? ' , list_has_duplicate_items( mylist )
print 'Redundant item(s) in list: ' , get_duplicate_items( mylist )
Reference https://www.daniweb.com/software-development/python/threads/286996/get-redundant-items-in-list
Using a similar approach to others here, heres my attempt:
from collections import Counter
def return_more_then_one(myList):
counts = Counter(my_list)
out_list = [i for i in counts if counts[i]>1]
return out_list
It can be as simple as ...
print(list(set([i for i in mylist if mylist.count(i) > 1])))
Use set to help you do that, like this maybe :
X = ['A','A','B','C','D','E','D']
Y = set(X)
Z = []
for val in Y :
occurrences = X.count(val)
if(occurrences > 1) :
#print(val,'occurs',occurrences,'times')
Z.append(val)
print(Z)
The list Z will save the list item which occur more than once. And the part I gave comment (#), that will show the number of occurrences of each list item which occur more than once
Might not be as fast as internal implementations, but takes (almost) linear time (since set lookup is logarithmic)
mylist = ['A','A','B','C','D','E','D']
myset = set()
dups = set()
for x in mylist:
if x in myset:
dups.add(x)
else:
myset.add(x)
dups = list(dups)
print dups
another solution what's written:
def delete_rep(list_):
new_list = []
for i in list_:
if i not in list_[i:]:
new_list.append(i)
return new_list
This is my approach without using packages
result = []
for e in listy:
if listy.count(e) > 1:
result.append(e)
else:
pass
print(list(set(result)))

Categories