python edit tuple duplicates in a list - python

my target is:
while for looping a list I would like to check for duplicates and if there are some i would like to append a number to it see following example
my list output as an example:
[('name','company'), ('someguy','microsoft'), ('anotherguy','microsoft'), ('thirdguy','amazon')]
in a loop i would like to edit those duplicates so instead of the 2nd microsoft i would like to have microsoft1 (if there would be 3 microsoft guys so the third guy would have microsoft2)
with this i can filter the duplicates but i dont know how to edit them directly in the list
list = [('name','company'), ('someguy','microsoft'), ('anotherguy','microsoft'), ('thirdguy','amazon')]
names = []
double = []
for u in list[1:]:
names.append(u[1])
list_size = len(names)
for i in range(list_size):
k = i + 1
for j in range(k, list_size):
if names[i] == names[j] and names[i] not in double:
double.append(names[i])

This is one approach using collections.defaultdict.
Ex:
from collections import defaultdict
lst = [('name','company'), ('someguy','microsoft'), ('anotherguy','microsoft'), ('thirdguy','amazon')]
seen = defaultdict(int)
result = []
for k, v in lst:
if seen[v]:
result.append((k, "{}_{}".format(v, seen[v])))
else:
result.append((k,v))
seen[v] += 1
print(result)
Output:
[('name', 'company'),
('someguy', 'microsoft'),
('anotherguy', 'microsoft_1'),
('thirdguy', 'amazon')]

Related

How can I cut a list into a list of lists based on the presence of a particular string?

I'll try my best to explain.
Say I have this; it represents a username (ex: jjo), an optional real name (ex: josh) and it's always followed by a "remove".
list_of_people = ['jjo','josh','remove','flor30','florentina','remove','mary_h','remove','jasoncel3','jason celora','remove', 'lashit', 'remove']
My goal is to achieve this:
cut_list = [ ['jjo','josh'], ['flor30', 'florentina'], ['mary_h'], ['jasoncel3', 'jason celora'], ['lashit']]
The problem here is that the real name is optional and therefore, it's not always a perfect "trio". In other words, I need to use the presence of "remove" as a pivot to cut my list.
Verbally speaking, I would say that the code would be:
if you meet "remove", go backwards and store everything until you meet another "remove"
One issue is that there's no "remove" at the start (although I could manually add it), but my main issue is the logic. I can't get it right.
Here's my "best" shot so far and what it gives:
list_of_people = ['jjo','josh','remove','flor30','florentina','remove','mary_h','remove','jasoncel3','jason celora','remove', 'lashit', 'remove']
#Add the first 2 items
#If "remove" is there (means there was no real name), remove it
#Turn list into a list of lists
cut_list = list_of_people[0:2]
if "remove" in cut_list:
cut_list.remove("remove")
cut_list = [cut_list]
#Loop through and cut based on the presence of "remove"
for i in range(2, len(list_of_people)):
if list_of_people[i] == 'remove':
first_back = list_of_people[i-1]
if list_of_people.append(list_of_people[i-2]) != 'remove':
second_back = list_of_people[i-2]
cut_list.append([first_back, second_back])
print(cut_list)
# #Should give:
# ##cut_list = [ ['jjo','josh'], ['flor30', 'florentina'], ['mary_h'], ['jasoncel3', 'jason celora'], ['lashit']]
[['jjo', 'josh'], ['josh', 'jjo'], ['josh', 'jjo'], ['josh', 'jjo'],
['florentina', 'flor30'], ['florentina', 'flor30'], ['mary_h',
'remove'], ['mary_h', 'remove'], ['mary_h', 'remove'], ['jason
celora', 'jasoncel3'], ['jason celora', 'jasoncel3'], ['lashit',
'remove']]
I chose to keep this simple and iterate once through the list using the ”remove” as the marker to do additional processing.
list_of_people = ['jjo','josh','remove','flor30','florentina','remove','mary_h','remove','jasoncel3','jason celora','remove', 'lashit', 'remove']
result = []
user = []
for name in list_of_people:
if name != "remove":
# Add to the people list
user.append(name)
else:
# Found a remove, reset `user` after adding to result
result.append(user)
user = []
print(result)
from itertools import groupby
sentence = ['jjo', 'josh', 'remove', 'flor30', 'florentina', 'remove', 'mary_h',
'remove', 'jasoncel3', 'jason celora', 'remove', 'lashit', 'remove']
i = (list(g) for _, g in groupby(sentence, key='remove'.__ne__))
l = [a + b for a, b in zip(i, i)]
N = 'remove'
res = [[ele for ele in sub if ele != N] for sub in l]
print(res)
Try:
from itertools import groupby
out = [
list(g) for v, g in groupby(list_of_people, lambda x: x != "remove") if v
]
print(out)
Prints:
[['jjo', 'josh'], ['flor30', 'florentina'], ['mary_h'], ['jasoncel3', 'jason celora'], ['lashit']]
Alternate version of #Jarvis's answer:
a= ['jjo','josh','remove','flor30','florentina','remove','mary_h','remove','jasoncel3','jason celora','remove', 'lashit', 'remove']
b=[]
start_index=0
for i,j in enumerate(a):
if j=='remove':
b.append(a[start_index:i])
start_index=i+1
print(b)
Logic:
Using append, append the whole list from start_index(which is 0 at intial) to to index of 'remove'
Then reset the start_index` to the index of 'remove' + 1.
(index of 'remove) + 1 to remove 'remove' in the output.

How can i create a dictionary from 2 lists with one as the key and the other as as the value with only loops? Without using zip() or enumerate()

I wanna achieve this without any libraries or special functions just loops. I wanna have a main program that takes in 2 inputs which are the 2 lists and returns the dictionary like shown below.
Please enter the item names: Cans, bottles, boxes, jugs
please enter quantities : 20,34,10
output : {'Cans':'20','bottles':'34','boxes':'10','jugs':'0'}
If the list of items is longer than the quantities then the quantity becomes automatically 0 as it did with the jugs above.
If the List of Quantity is longer than the items list then the item should automatically become 'unknown object_1' with the number changing accordingly.
Split with comma as delimiter. Fill values with zero for a number of iterations equal to the difference in length between keys and values.
Then use dict comprehension to build your dict. This with the zip built-in function.
keys = 'a,b,c,d'
values = '1,2,3'
keys = keys.split(',')
values = values.split(',')
for i in range(len(keys) - len(values)):
values.append('0')
dct = {}
for i in range(len(keys)):
dct[keys[i]] = values[i]
print(dct)
Output:
{'a': '1', 'b': '2', 'c': '3', 'd': '0'}
This uses only built-in calls so it fits your requirements at best. At the OP requirements it is not using the zip function.
item_names = ['Cans', 'Bottles', 'boxes', 'jugs']
quantities = [20, 34, 10]
output_dict = {}
for i, item in enumerate(item_names):
if i > len(quantities) - 1:
output_dict.update({item : 0})
else:
output_dict.update({item : quantities[i]})
a = list(input().split(','))
b = list(map(int, input().split(',')))
res = {}
for i in range(len(a)):
res[a[i]] = b[i] if i < len(b) else 0
print(res)
list1 = ['cans','Bottles','Boxes','Jugs']
list2 = [1,2,3]
res = {}
for i, element in enumerate(list1):
try:
res[element] = list2[i]
except IndexError:
res[element] = 0
print(res)
Edited code without enumerate or zip:
list1 = ['cans','Bottles','Boxes','Jugs']
list2 = [1,2,3]
res = {}
i=0
for element in list1:
try:
res[element] = list2[i]
except IndexError:
res[element] = 0
i+=1
print(res)
```

What is an easy way to remove duplicates from only part of the string in Python?

I have a list of strings that goes like this:
1;213;164
2;213;164
3;213;164
4;213;164
5;213;164
6;213;164
7;213;164
8;213;164
9;145;112
10;145;112
11;145;112
12;145;112
13;145;112
14;145;112
15;145;112
16;145;112
17;145;112
1001;1;151
1002;2;81
1003;3;171
1004;4;31
I would like to remove all duplicates where second 2 numbers are the same. So after running it through program I would get something like this:
1;213;164
9;145;112
1001;1;151
1002;2;81
1003;3;171
1004;4;31
But something like
8;213;164
15;145;112
1001;1;151
1002;2;81
1003;3;171
1004;4;31
would also be correct.
Here is a nice and fast trick you can use (assuming l is your list):
list({ s.split(';', 1)[1] : s for s in l }.values())
No need to import anything, and fast as can be.
In general you can define:
def custom_unique(L, keyfunc):
return list({ keyfunc(li): li for li in L }.values())
You can group the items by this key and then use the first item in each group (assuming l is your list).
import itertools
keyfunc = lambda x: x.split(";", 1)[1]
[next(g) for k, g in itertools.groupby(sorted(l, key=keyfunc), keyfunc)]
Here is a code on the few first items, just switch my list with yours:
x = [
'7;213;164',
'8;213;164',
'9;145;112',
'10;145;112',
'11;145;112',
]
new_list = []
for i in x:
check = True
s_part = i[i.find(';'):]
for j in new_list:
if s_part in j:
check = False
if check == True:
new_list.append(i)
print(new_list)
Output:
['7;213;164', '9;145;112']

Python sorting using for loop

I have written a for loop to display names in python idle as shown below.
1.SRA-D12-TY2-2017WW22.4.129
2.SRA-D12-TY2-2017WW27.5.168
3.SRA-D12-TY2-2017WW16.5.92
4.SRA-D12-TY2-2017WW20.2.115
5.SRA-D12-TY2-2017WW25.2.149
6.SRA-D12-TY2-2017WW29.5.188
7.SRA-D12-TY2-2017WW36.1.234
8.SRA-D12-TY2-2017WW31.3.201
The code I have written to display the above items is
for i in data.get('files'):
new_data = i.get('uri').strip('/')
platform_display = "{}.{}".format(count,new_data)
platform_dict[count] = new_data
count += 1
print platform_display
I want it to be displayed as
1.SRA-D12-TY2-2017WW36.1.234
2.SRA-D12-TY2-2017WW31.3.201
3.SRA-D12-TY2-2017WW29.5.188
etc in descending order
Please let me know how can I sort the names
l1=[
'SRA-D12-TY2-2017WW22.4.129',
'SRA-D12-TY2-2017WW27.5.168',
'SRA-D12-TY2-2017WW16.5.92',
'SRA-D12-TY2-2017WW20.2.115',
'SRA-D12-TY2-2017WW25.2.149',
'SRA-D12-TY2-2017WW29.5.188',
'SRA-D12-TY2-2017WW36.1.234',
'SRA-D12-TY2-2017WW31.3.201'
]
l1=sorted(l1, key=lambda x: x.split("WW")[-1],reverse=True)
for i in l1:
print(i)
Output:
SRA-D12-TY2-2017WW36.1.234
SRA-D12-TY2-2017WW31.3.201
SRA-D12-TY2-2017WW29.5.188
SRA-D12-TY2-2017WW27.5.168
SRA-D12-TY2-2017WW25.2.149
SRA-D12-TY2-2017WW22.4.129
SRA-D12-TY2-2017WW20.2.115
SRA-D12-TY2-2017WW16.5.92
Just use reversed sort.
Lets say all your item in the list called l,
l=['SRA-D12-TY2-2017WW22.4.129',
'SRA-D12-TY2-2017WW27.5.168',
'SRA-D12-TY2-2017WW16.5.92',
'SRA-D12-TY2-2017WW20.2.115',
'SRA-D12-TY2-2017WW25.2.149',
'SRA-D12-TY2-2017WW29.5.188',
'SRA-D12-TY2-2017WW36.1.234',
'SRA-D12-TY2-2017WW31.3.201']
sorted(l, reverse=True)
Try this:
from operator import itemgetter
platform_list = []
for i in data.get('files'):
new_data = i.get('uri').strip('/')
platform_list.append([new_data.split("WW")[-1],new_data])
first_item = itemgetter(0)
new_list = sorted(platform_list, key = first_item)
counter = 0
for i in new_list:
counter += 1
print "%d.%s" %(counter,i[1])

Merge nested list items based on a repeating value

Although poorly written, this code:
marker_array = [['hard','2','soft'],['heavy','2','light'],['rock','2','feather'],['fast','3'], ['turtle','4','wet']]
marker_array_DS = []
for i in range(len(marker_array)):
if marker_array[i-1][1] != marker_array[i][1]:
marker_array_DS.append(marker_array[i])
print marker_array_DS
Returns:
[['hard', '2', 'soft'], ['fast', '3'], ['turtle', '4', 'wet']]
It accomplishes part of the task which is to create a new list containing all nested lists except those that have duplicate values in index [1]. But what I really need is to concatenate the matching index values from the removed lists creating a list like this:
[['hard heavy rock', '2', 'soft light feather'], ['fast', '3'], ['turtle', '4', 'wet']]
The values in index [1] must not be concatenated. I kind of managed to do the concatenation part using a tip from another post:
newlist = [i + n for i, n in zip(list_a, list_b]
But I am struggling with figuring out the way to produce the desired result. The "marker_array" list will be already sorted in ascending order before being passed to this code. All like-values in index [1] position will be contiguous. Some nested lists may not have any values beyond [0] and [1] as illustrated above.
Quick stab at it... use itertools.groupby to do the grouping for you, but do it over a generator that converts the 2 element list into a 3 element.
from itertools import groupby
from operator import itemgetter
marker_array = [['hard','2','soft'],['heavy','2','light'],['rock','2','feather'],['fast','3'], ['turtle','4','wet']]
def my_group(iterable):
temp = ((el + [''])[:3] for el in marker_array)
for k, g in groupby(temp, key=itemgetter(1)):
fst, snd = map(' '.join, zip(*map(itemgetter(0, 2), g)))
yield filter(None, [fst, k, snd])
print list(my_group(marker_array))
from collections import defaultdict
d1 = defaultdict(list)
d2 = defaultdict(list)
for pxa in marker_array:
d1[pxa[1]].extend(pxa[:1])
d2[pxa[1]].extend(pxa[2:])
res = [[' '.join(d1[x]), x, ' '.join(d2[x])] for x in sorted(d1)]
If you really need 2-tuples (which I think is unlikely):
for p in res:
if not p[-1]:
p.pop()
marker_array = [['hard','2','soft'],['heavy','2','light'],['rock','2','feather'],['fast','3'], ['turtle','4','wet']]
marker_array_DS = []
marker_array_hit = []
for i in range(len(marker_array)):
if marker_array[i][1] not in marker_array_hit:
marker_array_hit.append(marker_array[i][1])
for i in marker_array_hit:
lists = [item for item in marker_array if item[1] == i]
temp = []
first_part = ' '.join([str(item[0]) for item in lists])
temp.append(first_part)
temp.append(i)
second_part = ' '.join([str(item[2]) for item in lists if len(item) > 2])
if second_part != '':
temp.append(second_part);
marker_array_DS.append(temp)
print marker_array_DS
I learned python for this because I'm a shameless rep whore
marker_array = [
['hard','2','soft'],
['heavy','2','light'],
['rock','2','feather'],
['fast','3'],
['turtle','4','wet'],
]
data = {}
for arr in marker_array:
if len(arr) == 2:
arr.append('')
(first, index, last) = arr
firsts, lasts = data.setdefault(index, [[],[]])
firsts.append(first)
lasts.append(last)
results = []
for key in sorted(data.keys()):
current = [
" ".join(data[key][0]),
key,
" ".join(data[key][1])
]
if current[-1] == '':
current = current[:-1]
results.append(current)
print results
--output:--
[['hard heavy rock', '2', 'soft light feather'], ['fast', '3'], ['turtle', '4', 'wet']]
A different solution based on itertools.groupby:
from itertools import groupby
# normalizes the list of markers so all markers have 3 elements
def normalized(markers):
for marker in markers:
yield marker + [""] * (3 - len(marker))
def concatenated(markers):
# use groupby to iterator over lists of markers sharing the same key
for key, markers_in_category in groupby(normalized(markers), lambda m: m[1]):
# get separate lists of left and right words
lefts, rights = zip(*[(m[0],m[2]) for m in markers_in_category])
# remove empty strings from both lists
lefts, rights = filter(bool, lefts), filter(bool, rights)
# yield the concatenated entry for this key (also removing the empty string at the end, if necessary)
yield filter(bool, [" ".join(lefts), key, " ".join(rights)])
The generator concatenated(markers) will yield the results. This code correctly handles the ['fast', '3'] case and doesn't return an additional third element in such cases.

Categories