Related
I, have a dictionary say {0:[1,2,3],1[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}. there are some duplicate values but the keys are different. when i append a value to list corresponding to key 0 python also adds the value to other duplicates what i don't need.
my code :-
for k, v in f.items():
if k == 0:
v.append(1)
result:-
{0:[1,2,3,1],1[1,2,3,1],2:[1,2,3,1],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
what i want is :-
{0:[1,2,3,1],1[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
I guess your dictionary is faulty. It should be like this:
f={0:[1,2,3],1:[1,2,3],2:[1,2,3],3:[1,2,4],4:[1,2,4],5:[1,2,4]}
for k,v in f.items():
if k==0:
v.append(1)
print(f)
Output: {0: [1, 2, 3, 1], 1: [1, 2, 3], 2: [1, 2, 3], 3: [1, 2, 4], 4: [1, 2, 4], 5: [1, 2, 4]}
Isn't it what you want?
I have dictionary that represents tree without weights:
dict = {1: [1, 3], 2: [2, 3], 3: [3, 5], 4: [4, 5], 5: [2, inf], 6: []}
It contains only integers.
I want to print out path from the key that contains 'inf' like this:
5-2-2-3-3-5
What is the easiest way to do it? If using while loop, what statement should it have?
You need three things to accomplish this:
A store of how many times you've visited a particular index
A method of translating the information in 1 into the proposed next key to visit
You need to repeat this procedure while your next key is in your dict.
Possible implementation:
dict = {1: [1, 3], 2: [2, 3], 3: [3, 5], 4: [4, 5], 5: [2, 'inf'], 6: []}
visit = {}
path = []
next_key = 5
while next_key in dict:
this_key = next_key
path.append(this_key)
try:
next_key = dict[this_key][visit.setdefault(this_key, 0)]
visit[this_key] += 1
except:
break
# Result
print(*path, sep='-')
Is there a possibility to create a dict from two lists with same key occurring multiple times without iterating over the whole dataset?
Minimal example:
keys = [1, 2, 3, 2, 3, 4, 5, 1]
values = [1, 2, 3, 4, 5, 6, 7, 8]
# hoped for result:
dictionary = dict(???)
dictionary = {1 : [1,8], 2:[2,4], 3:[3,5], 4:[6], 5:[7]}
When using zip the key-value-pair is inserted overwriting the old one:
dictionary = dict(zip(keys,values))
dictionary = {1: 8, 2: 4, 3: 5, 4: 6, 5: 7}
I would be happy with a Multidict as well.
This is one approach that doesn't require 2 for loops
h = defaultdict(list)
for k, v in zip(keys, values):
h[k].append(v)
print(h)
# defaultdict(<class 'list'>, {1: [1, 8], 2: [2, 4], 3: [3, 5], 4: [6], 5: [7]})
print(dict(h))
# {1: [1, 8], 2: [2, 4], 3: [3, 5], 4: [6], 5: [7]}
This is the only one-liner I could do.
dictionary = {k: [values[i] for i in [j for j, x in enumerate(keys) if x == k]] for k in set(keys)}
It is far from readable. Remember that clear code is always better than pseudo-clever code ;)
Here is an example that I think is easy to follow logically. Unfortunately it does not use zip like you would prefer, nor does it avoid iterating, because a task like this has to involve iterating In some form.
# Your data
keys = [1, 2, 3, 2, 3, 4, 5, 1]
values = [1, 2, 3, 4, 5, 6, 7, 8]
# Make result dict
result = {}
for x in range(1, max(keys)+1):
result[x] = []
# Populate result dict
for index, num in enumerate(keys):
result[num].append(values[index])
# Print result
print(result)
If you know the range of values in the keys array, you could make this faster by providing the results dictionary as a literal with integer keys and empty list values.
I have a list. Let's say [3,4,2,3,4,2,1,4,5].
I need to create a dictionary from the indexes of the elements.
Here in this case, I need to create a dict as follows:
{
'3':[0,3],
'4':[1,4,7],
'2':[2,5],
'1':[6],
'5':[8]
}
where the element values are the indexes of the keys in list provided.
I've tried. But was able to change the values as integers only. But unable to make them as list.
Is there any way to do this with just 1 for loop?
The code I've tried:
d=dict()
ll=[1,2,1,2,1,2,3,4,5,5,4,2,4,6,5,6,78,3,2,4,5,7,8,9,4,4,2,2,34,5,6,3]
for i,j in enumerate(ll):
d[j].append(i)
print(d)
You can use collections.defaultdict with enumerate for an O(n) solution:
from collections import defaultdict
d = defaultdict(list)
A = [3,4,2,3,4,2,1,4,5]
for idx, val in enumerate(A):
d[val].append(idx)
print(d)
defaultdict(list, {1: [6], 2: [2, 5], 3: [0, 3], 4: [1, 4, 7], 5: [8]})
This will work, the key thing you're looking for is the enumerate() function:
list_to_convert = [3,4,2,3,4,2,1,4,5]
out_dict = {}
for idx, val in enumerate(list_to_convert):
if val in out_dict:
out_dict[val].append(idx)
else:
out_dict[val] = [idx,]
print (out_dict)
Gives:
{3: [0, 3], 4: [1, 4, 7], 2: [2, 5], 1: [6], 5: [8]}
mylist = [3, 4, 2, 3, 4, 2, 1, 4, 5]
d = {}
for index, item in enumerate(mylist):
d.setdefault(item, []).append(index)
results in
{3: [0, 3], 4: [1, 4, 7], 2: [2, 5], 1: [6], 5: [8]}
Why? Well, we iterate over the list, and for each item, we first make sure that there is a list in the dictionary mapped to by this item. Then we append the respective index to that list. What results is a dictionary which maps each seen item to a list of indexes it was found at.
The solution is similar to jpp's solution, except of the part with .setdefault(), which creates an empty list in every loop run, while the defaultdict approach only creates new lists if needed.
Another approach could be a dict subclass which implements __missing__. This is called whenever a key isn't present.
class ListDict(dict):
def __missing__(self, key):
l = []
self[key] = l
return l
and then just do d[item].append(index). Now, whenever a key is not found, __missing__() is called which "fixes" the problem. See also How can I call __missing__ from dict for this.
You can use a set:
d = [3,4,2,3,4,2,1,4,5]
new_d = {i:[c for c, a in enumerate(d) if i == a] for i in set(d)}
Output:
{1: [6], 2: [2, 5], 3: [0, 3], 4: [1, 4, 7], 5: [8]}
I am trying to merge two lists based on position of index, so sort of a proximity intersection.
A set doesn't work in this case. What i am trying to do is match index in each list then if the element is one less than that of the element in other list, only then i collect it.
An example will explain my scenario better.
Sample Input:
print merge_list([[0, 1, 3], [1, 2], [4, 1, 3, 5]],
[[0, 2, 6], [1, 4], [2, 2], [4, 1, 6]])
Sample Output:
[[0,2],[4,6]]
so on position 0 in list1 we have 1, 3 and in list2 we have 2, 6. Since 1 is one less than 2, so we collect that and move on, now 3 is less than 6 but it's not one less than i.e. not 5 so we ignore that. Next we have [1, 2][1, 4], so both index/position 1, but 2 is not one less than 4 so we ignore that. Next we have [2, 2] in list2 both index 2 doesn't match any index in first list so no comparison. Finally we have [4, 1, 3, 5] [4, 1, 6] comparison. Both index match and only 5 in list one is one less than list two so we collect six hence we collect [4,6] meaning index 4 and match etc.
I have tried to make it work, but i don't seem to make it work.
This is my code so far.
def merge_list(my_list1, my_list2):
merged_list = []
bigger_list = []
smaller_list = []
temp_outer_index = 0
temp_inner_index = 0
if(len(my_list1) > len(my_list2)):
bigger_list = my_list1
smaller_list = my_list2
elif(len(my_list2) > len(my_list1)):
bigger_list = my_list2
smaller_list = my_list1
else:
bigger_list = my_list1
smaller_list = my_list2
for i, sublist in enumerate(bigger_list):
for index1 , val in enumerate(sublist):
for k, sublist2 in enumerate(smaller_list):
for index2, val2 in enumerate(sublist2):
temp_outer_index = index1 + 1
temp_inner_index = index2 + 1
if(temp_inner_index < len(sublist2) and temp_outer_index < len(sublist)):
# print "temp_outer:%s , temp_inner:%s, sublist[temp_outer]:%s, sublist2[temp_inner_index]:%s" % (temp_outer_index, temp_inner_index, sublist[temp_outer_index], sublist2[temp_inner_index])
if(sublist2[temp_inner_index] < sublist[temp_outer_index]):
merged_list.append(sublist[temp_outer_index])
break
return merged_list
No clue what you are doing, but this should work.
First, convert the list of lists to a mapping of indices to set of digits contained in that list:
def convert_list(l):
return dict((sublist[0], set(sublist[1:])) for sublist in l)
This will make the lists a lot easier to work with:
>>> convert_list([[0, 1, 3], [1, 2], [4, 1, 3, 5]])
{0: set([1, 3]), 1: set([2]), 4: set([1, 3, 5])}
>>> convert_list([[0, 2, 6], [1, 4], [2, 2], [4, 1, 6]])
{0: set([2, 6]), 1: set([4]), 2: set([2]), 4: set([1, 6])}
Now the merge_lists function can be written as such:
def merge_lists(l1, l2):
result = []
d1 = convert_list(l1)
d2 = convert_list(l2)
for index, l2_nums in d2.items():
if index not in d1:
#no matching index
continue
l1_nums = d1[index]
sub_nums = [l2_num for l2_num in l2_nums if l2_num - 1 in l1_nums]
if sub_nums:
result.append([index] + sorted(list(sub_nums)))
return result
Works for your test case:
>>> print merge_lists([[0, 1, 3], [1, 2], [4, 1, 3, 5]],
[[0, 2, 6], [1, 4], [2, 2], [4, 1, 6]])
[[0, 2], [4, 6]]
I believe this does what you want it to do:
import itertools
def to_dict(lst):
dct = {sub[0]: sub[1:] for sub in lst}
return dct
def merge_dicts(a, b):
result = []
overlapping_keys = set.intersection(set(a.keys()), set(b.keys()))
for key in overlapping_keys:
temp = [key] # initialize sublist with index
for i, j in itertools.product(a[key], b[key]):
if i == j - 1:
temp.append(j)
if len(temp) > 1: # if the sublist has anything besides the index
result.append(temp)
return result
dict1 = to_dict([[0, 1, 3], [1, 2], [4, 1, 3, 5]])
dict2 = to_dict([[0, 2, 6], [1, 4], [2, 2], [4, 1, 6]])
result = merge_dicts(dict1, dict2)
print(result)
Result:
[[0, 2], [4, 6]]
First, we convert your lists to dicts because they're easier to work with (this separates the key out from the other values). Then, we look for the keys that exist in both dicts (in the example, this is 0, 1, 4) and look at all pairs of values between the two dicts for each key (in the example, 1,2; 1,6; 3,2; 3,6; 2,4; 1,1; 1,6; 3,1; 3,6; 5,1; 5,6). Whenever the first element of a pair is one less than the second element, we add the second element to our temp list. If the temp list ends up containing anything besides the key (i.e. is longer than 1), we add it to the result list, which we eventually return.
(It just occurred to me that this has pretty bad performance characteristics - quadratic in the length of the sublists - so you might want to use Claudiu's answer instead if your sublists are going to be long. If they're going to be short, though, I think the cost of initializing a set is large enough that my solution might be faster.)
def merge_list(a, b):
d = dict((val[0], set(val[1:])) for val in a)
result = []
for val in b:
k = val[0]
if k in d:
match = [x for x in val[1:] if x - 1 in d[k]]
if match:
result.append([k] + match)
return result
Similar to the other answers, this will first convert one of the lists to a dictionary with the first element of each inner list as the key and the remainder of the list as the value. Then we walk through the other list and if the first element exists as a key in the dictionary, we find all values that meet your criteria using the list comprehension and if there were any, add an entry to the result list which is returned at the end.