I have a list of tuples as seen below :
l = [(1,'Nick'),(4,'George'),(4,'George'),(3,'Nick')]
what i would like to do is merge the tuples with the same Name and add the corresponding numbers.
Result here should be :
l_res = [(4,'Nick'),(8,'George')]
How could this be done using python?
You can use a combination of set and list comprehensions like this:
>>> l = [(1,'Nick'),(4,'George'),(4,'George'),(3,'Nick')]
>>> unique = set(e[1] for e in l)
>>> [(sum([x[0] for x in l if x[1] == n]), n) for n in unique]
[(8, 'George'), (4, 'Nick')]
You can use an intermediate set as suggested in a previous answer or with an intermediate dictionary like this:
l = [(1,'Nick'),(4,'George'),(4,'George'),(3,'Nick')]
d = dict()
for v, t in l:
d[t] = d.get(t, 0) + v
result = [(v, k) for k, v in d.items()]
print(result)
Output:
[(4, 'Nick'), (8, 'George')]
Probably the cleanest way is by using a Counter dictionary.
from collections import Counter
l = [(1,'Nick'),(4,'George'),(4,'George'),(3,'Nick')]
sum_dict = Counter()
for el in l:
sum_dict[el[1]] += el[0]
print(sum_dict) # Output: Counter({'George': 8, 'Nick': 4})
If you really want a list of tuples (which doesn't seem like the best datatype for this data), you can easily convert it with list comprehension over dict.items()
sum_list = [(v,k) for k,v in sum_dict.items()]
print(sum_list) # Output: [('Nick', 4), ('George', 8)]
You want to turn l_res into a dict by name, adding the numbers:
dic = {}
for tup in l:
num, name = tup
if name in dic:
dic[name] += num
else:
dic[name] = num
to turn it back into a list:
l_res = [(dic[k], k) for k in dic]
Related
Is it possible to convert from a list of pair of elements like this:
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
to an adjacency list like this below:
{'yellow':['1', '3'], 'blue':['2','4'], 'red':['1']}
Use a defaultdict:
from collections import defaultdict
d = defaultdict(list)
for k, v in s:
d[k].append(v)
This will allow you to append items to the lists (elements of the dictionary) as if they were there, and if they are not, they will be created as empty lists for you.
This is not doing anything that could not also be done more manually with:
d = {}
for k, v in s:
if k not in d:
d[k] = []
d[k].append(v)
Note: if you really want the elements of these lists to be strings, then do:
d[k].append(str(v))
Use the groupby function. Mind that you have to sort the list first.
You can do like:
m = {}
for key, value in s:
m.setdefault(key, []).append(value)
print(m)
I've found the answer, thanks
result = {}
for i in follower_list:
result.setdefault(i[0], []).append(i[1])
I have a dictionary which has values as:
m = {1: 2, 7: 3, 2: 1, 4: 4, 5: 3, 6: 9}
The required output should be cyclic values like 1:2 -> 2:1 = cycle, which both are present in dictionary. 4:4 is also a cycle.
My output should be
[(1, 2), [4]]
CODE
m = {1: 2, 7: 3, 2: 1, 4: 4, 5: 3, 6: 9}
k = list(m.items())
print(k)
p = [t[::-1] for t in k]
print(p)
my_list = [(a, b) for (a, b) in p for (c, d) in k if ((a ==c) and (b == d))]
for i in k:
if i in my_list:
print("cycles : ", i)
OUTPUT:
The output I am getting is
cycles : (1, 2)
cycles : (2, 1)
cycles : (4, 4)
Can someone help me out with this?
Let's split this into two steps. First we'll find the cycles. Then we'll format the output however you want.
Finding cycles is easy, given that you have a dictionary: values become keys, making lookup fast. We can store the cycles in sorted order in a set to avoid duplicates:
cycles = set()
for k, v in m.items():
if m.get(v) == k:
cycles.add(tuple(sorted((k, v))))
Not that I'd recommend it, but the above can be written as an illegible one-liner:
cycles = set(tuple(sorted(item)) for item in m.items() if m.get(item[1]) == item[0])
Now to format the data. You want a list output, and entries with duplicates formatted as lists:
output = [[k] if k == v else (k, v) for k, v in cycles]
If you don't like clean code, you can imagine how to turn the whole operation into a one-liner :)
Update
It's worth considering the case where cycles are longer than one or two entries. You seem to want to store only one element per cycle, so let's do that. We can follow the chain from each element in the dictionary. If any part of the chain makes a cycle, we can find the minimum element of the cycle to report, and remove all the visited elements, since they are all no longer under consideration:
def find_cycles(m):
n = m.copy() # don't mutilate the original
cycles = []
while n:
visited = {}
count = 0
k, v = n.popitem()
while v is not None:
visited[k] = (count, v)
count += 1
k = v
v = n.pop(k, None)
if k in visited:
cycle_start = visited[k][0]
item = min((k, v) for k, (c, v) in visited.items() if c >= cycle_start)
cycles.append(item)
return [[k] if k == v else (k, v) for k, v in cycles]
For example:
>>> find_cycles({1:2, 2:3, 3:4, 4:5, 5:1, 6:1, 7:1, 8:8})
[(1, 2), [8]]
A better generalization might be to return a tuple with the entire cycle in it, starting with the smallest key. Mostly the statements under if k in visited: need to change to do that:
visited[k] = count
...
if k in visited:
if len(visited) == 1:
cycle = list(visited.keys())
else:
cycle_start = visited[k]
cycle = sorted((c, k) for k, c in visited.items() if c >= cycle_start)
cycle = tuple(k for c, k in cycle)
k = min(range(len(cycle)), key=lambda x: cycle[x])
cycle = cycle[k:] + cycle[:k]
cycles.append(cycle)
return cycles
This version is more informative:
>>> find_cycles({1:2, 2:3, 3:4, 4:5, 5:1, 6:1, 7:1, 8:8})
[(1, 2, 3, 4, 5), [8]]
Here is my IDEOne scratchspace in case you're interested: https://ideone.com/6kpRrW
Edited
Hey you have to just replace the pair with any other symbol in the list once it is found. Then it gives you the desired results.
map = {1:2, 7:3, 2:1, 4:4, 5:3, 6:9}
k = list(map.items())
print(k)
result = []
for i in k:
if i != -1 and i[::-1] in k:
result.append((set(i)))
k[k.index(i[::-1])] = -1
print(result)
#if you want tuples as output
[print(tuple(x),end = " ") for x in result]
I currently have the dictionary:
matrix = {(0, 0): 1, (1, 1): 1, (2, 2): 1}
And I need to create a single string that displays:
(0,0,1),(1,1,1),(2,2,1)
How can I join the dictionary keys (tuples) and value together into one string?
I was thinking of putting the keys into a list and adding the key into the list, but I am not entirely sure how to add it in the right order given that tuples are immutable.
result = []
for i, j in matrix.items():
result.append(i)
for i in result:
The basic operation you're looking for is:
[k + (v,) for k, v in matrix.items()]
To print that in your specific way, you probably want:
print(', '.join(str(k + (v,)) for k, v in matrix.items()))
Note that dictionaries are unordered, so the order of the result is undefined.
Your approach will keep them in the right order. The only thing it looks like you need to change in your code is splitting the tuple into its sub-parts:
>>> result = []
>>> for (x, y), z in matrix.items():
result.append((x, y, z))
>>> print result
[(0, 0, 1), (1, 1, 1), (2, 2, 1)]
I don't know whether this is the most pythonic solution but try this:
str(tuple(_ + (matrix[_],) for _ in matrix))
Or use %s:
print(','.join(["(%s,%s,%s)"%(*k,v) for k,v in matrix.items()]))
Or:
print(','.join([str((*k,v)) for k,v in matrix.items()]))
Or if version not above python 3.5:
print(','.join(["(%s,%s,%s)"%k+(v,) for k,v in matrix.items()]))
Or:
print(','.join([str(k+(v,)) for k,v in matrix.items()]))
Building off your work so far:
lst = []
for i,j in matrix.items():
lst.append((i[0],i[1],j))
result = ",".join( repr(e) for e in lst )
Please note that your keys are tuples which are immutable so cannot be modified, so you need to unpack them first and then join with the dictionary value.
You can use,
matrix = {(0, 0): 1, (1, 1): 1, (2, 2): 1}
# *k unpack keys
print(','.join("({},{},{})".format(*k,v) for k,v in matrix.items()))
# output,
# (0,0,1),(1,1,1),(2,2,1)
def get_distinct(original_list):
distinct_list = []
for i in original_list:
if i not in distinct_list:
distinct_list.append(each)
return distinct_list
list_1 = [1,2,3,4,4,5,6,6]
print(get_distinct(list_1))
So I want it to print 1, 2, 3, 5 instead of 1,2,3,4,5,6
collections.Counter() is good way to count things, e.g.:
from collections import Counter
def get_distinct(original_list):
return [k for k, v in Counter(original_list).items() if v == 1]
In []:
list_1 = [1,2,3,4,4,5,6,6]
get_distinct(list_1)
Out[]:
[1, 2, 3, 5]
While in 3.6 this will be in the order expected Counter() doesn't make any order guarantees, if you need it in the same order as in original_list then you can create a set and use that to test uniqueness, e.g.:
def get_distinct(original_list):
uniqs = {k for k, v in Counter(original_list).items() if v == 1}
return [e for e in original_list if e in uniqs]
print([x for x in list_1 if list_1.count(x) == 1])
Although using collections.Counter() is the best approach here, another option you can use is counting with a collections.defaultdict():
from collections import defaultdict
def get_distinct(original_list):
counts = defaultdict(int)
for item in original_list:
counts[item] += 1
return [k for k, v in counts.items() if v == 1]
Which works as follows:
>>> get_distinct([1,2,3,4,4,5,6,6])
[1, 2, 3, 5]
If you want to guarantee order, you can use a collections.OrderedDict():
from collections import OrderedDict
def get_distinct(original_list):
counts = OrderedDict()
for item in original_list:
counts[item] = counts.get(item, 0) + 1
return [k for k, v in counts.items() if v == 1]
How do I remove duplicates and combine multiple lists into one like so:
function([["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]) should return exactly:
[["good", ["me.txt", "money.txt"]], ["hello", ["me.txt"]], ["rep", ["money.txt"]]]
The easiest one would be using defaultdict .
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for i,j in l:
d[i].append(j) #append value to the key
>>> d
=> defaultdict(<class 'list'>, {'hello': ['me.txt'], 'good': ['me.txt', 'money.txt'],
'rep': ['money.txt']})
#to get it in a list
>>> out = [ [key,d[key]] for key in d]
>>> out
=> [['hello', ['me.txt']], ['good', ['me.txt', 'money.txt']], ['rep', ['money.txt']]]
#driver values :
IN : l = [["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
Try This ( no library needed ):
your_input_data = [ ["hello","me.txt"], ["good","me.txt"], ["good","me.txt"], ["good","money.txt"], ["rep", "money.txt"] ]
my_dict = {}
for box in your_input_data:
if box[0] in my_dict:
buffer_items = []
for items in box[1:]:
if items not in my_dict[box[0]]:
buffer_items.append(items)
remove_dup = list(set(buffer_items + my_dict[box[0]]))
my_dict[box[0]] = remove_dup
else:
buffer_items = []
for items in box[1:]:
buffer_items.append(items)
remove_dup = list(set(buffer_items))
my_dict[box[0]] = remove_dup
last_point = [[keys, values] for keys, values in my_dict.items()]
print(last_point)
Good Luck ...
You can do it with traditional dictionaries too.
In [30]: l1 = [["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
In [31]: for i, j in l1:
...: if i not in d2:
...: d2[i] = j
...: else:
...: val = d2[i]
...: d2[i] = [val, j]
...:
In [32]: d2
Out[32]: {'good': ['me.txt', 'money.txt'], 'hello': 'me.txt', 'rep': 'money.txt'}
In [33]: out = [ [key,d1[key]] for key in d1]
In [34]: out
Out[34]:
[['rep', ['money.txt']],
['hello', ['me.txt']],
['good', ['me.txt', 'money.txt']]]
Let's first understand the actual problem :
Example Hint :
For these types of list problems there is a pattern :
So suppose you have a list :
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
And you want to convert this to a dict as the first element of the tuple as key and second element of the tuple. something like :
{2008: [9], 2006: [5], 2007: [4]}
But there is a catch you also want that those keys which have different values but keys are same like (2006,1) and (2006,5) keys are same but values are different. you want that those values append with only one key so expected output :
{2008: [9], 2006: [1, 5], 2007: [4]}
for this type of problem we do something like this:
first create a new dict then we follow this pattern:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
So we first check if key is in new dict and if it already then add the value of duplicate key to its value:
full code:
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
new_dict={}
for item in a:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
print(new_dict)
Your actual problem solution :
list_1=[["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
no_dublicates={}
for item in list_1:
if item[0] not in no_dublicates:
no_dublicates[item[0]]=["".join(item[1:])]
else:
no_dublicates[item[0]].extend(item[1:])
list_result=[]
for key,value in no_dublicates.items():
list_result.append([key,value])
print(list_result)
output:
[['hello', ['me.txt']], ['rep', ['money.txt']], ['good', ['me.txt', 'money.txt']]]
yourList=[["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]
expectedList=[["good", ["me.txt", "money.txt"]], ["hello", ["me.txt"]], ["rep", ["money.txt"]]]
def getall(allsec, listKey, uniqlist):
if listKey not in uniqlist:
uniqlist.append(listKey)
return [listKey, [x[1] for x in allsec if x[0] == listKey]]
uniqlist=[]
result=sorted(list(filter(lambda x:x!=None, [getall(yourList,elem[0],uniqlist) for elem in yourList])))
print(result)
hope this helps
This can easily be solved using dict and sets.
def combine_duplicates(given_list):
data = {}
for element_1, element_2 in given_list:
data[element_1] = data.get(element_1, set()).add(element_2)
return [[k, list(v)] for k, v in data.items()]
Using Python to create a function that gives you the exact required output can be done as follows:
from collections import defaultdict
def function(data):
entries = defaultdict(list)
for k, v in data:
entries[k].append(v)
return sorted([k, v] for k, v in entries.items())
print(function([["hello","me.txt"],["good","me.txt"],["good","money.txt"], ["rep", "money.txt"]]))
The output is sorted before being returned as per your requirement. This would display the return from the function as:
[['good', ['me.txt', 'money.txt']], ['hello', ['me.txt']], ['rep', ['money.txt']]]
It also ensures that the keys are sorted. A dictionary is used to deal with the removal of duplicates (as keys need to be unique).
A defaultdict() is used to simplify the building of lists within the dictionary. The alternative would be to try and append a new value to an existing key, and if there is a KeyError exception, then add the new key instead as follows:
def function(data):
entries = {}
for k, v in data:
try:
entries[k].append(v)
except KeyError as e:
entries[k] = [v]
return sorted([k, v] for k, v in entries.items())
Create a empty array push the index 0 from childs arrays and join to convert all values to a string separate by space .
var your_input_data = [ ["hello","hi", "jel"], ["good"], ["good2","lo"], ["good3","lt","ahhahah"], ["rep", "nice","gr8", "job"] ];
var myprint = []
for(var i in your_input_data){
myprint.push(your_input_data[i][0]);
}
console.log(myprint.join(' '))