code review: Python list concatenation elements to string - python

hey i have a Problem solving a Problem
that Looks like this:
the Output is exactly what i need but i wonder is there isnt a more elegant
way to do that?
list = [["key189","0","apples"],
["key622","1","bananas"],
["key233","2","bacon"],
["key454","3","bread"],
["key35","4","jam"],
["key6","5","coffee"]]
for e in list:
if e[0] == "key622":
key622 = e[2]
if e[0] == "key189":
key189 = e[2]
if e[0] == "key35":
key35 = e[2]
if e[0] == "key454":
key454 = e[2]
if e[0] == "key233":
key233 = e[2]
if e[0] == "key6":
key6 = e[2]
string_form = "|".join([key6, key35, key233, key189, key622, key454])
print(string_form)
# prints coffee|jam|bacon|apples|bananas|bread

I think a using a dictionary will make your life easier.
dt = {itm[0]:itm[2] for itm in list}
dt will be:
{'key189': 'apples',
'key233': 'bacon',
'key35': 'jam',
'key454': 'bread',
'key6': 'coffee',
'key622': 'bananas'}
string_form = "|".join(dt.values())
string_form will be:
'coffee|apples|bacon|jam|bananas|bread'
you can get any key's value: like this:
dt.get('key35')
For the specific string use this:
"|".join([dt.get('key6'), dt.get('key35'), dt.get('key233'), dt.get('key189'), dt.get('key622'), dt.get('key454')])
Try not to use variable names like list, dict etc.

Since you didn't specify anything about order, this should do:
data = [["key189","0","apples"],
["key622","1","bananas"],
["key233","2","bacon"],
["key454","3","bread"],
["key35","4","jam"],
["key6","5","coffee"]]
print("|".join([pair[2] for pair in data]))

"|".join(fruit for _, _, fruit in list)

Instead of hardcording the order in an if-else construct, you could just define it in a list, and then sort according to the index the item has in that list:
order = ['key6', 'key35', 'key238', 'key189', 'key622', 'key454']
print("|".join(y[2] for y in sorted([x for x in lst if x[0] in order], key = lambda i: order.index(i[0]))))

Related

How to replace a numerical value in a Python list

So I got this list of lists:
lst = [[0,1],2,[3]]
and I got a list of tuples:
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
I want to replace values inside lst with the index 0 value of each of the tuples in lst_2, and the tuple taken depends on the numerical value in lst. So it becomes:
lst = [["x1","x2"], "x3", ["x4"]]
Please don't roast me thanks so much
Try this:
lst = [[0,1],2,[3]]
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
res = []
for l in lst:
if isinstance(l, list):
res += [[lst_2[i][0] for i in l]]
else:
res += [lst_2[l][0]]
print(res)
Or with List Comprehensions:
res = [[lst_2[i][0] for i in l] if isinstance(l, list) else lst_2[l][0] for l in lst]
[['x1', 'x2'], 'x3', ['x4']]
You could use recursion to allow lst to have deeper levels of nesting:
def produce(template, data):
return [
produce(nested, data) for nested in template
] if isinstance(template, list) else data[template][0]
# Example
lst = [[0,[1]],2,[3]]
lst_2 = [("x1","y1"),("x2","y2"), ("x3","y3"), ("x4","y4")]
result = produce(lst, lst_2)

trying to delete duplicate dictionary values from the list of dictionaries

below is my list of dictionaries:
I'm tried to remove the duplicate values from 'r_id'. some values are in list and some are in string.
list_of_dict = [{'fid':200, 'r_id':['4321', '4321']}, {'fid':201, 'r_id':'5321'}]
expected output
list_of_dict = [{'fid':200, 'r_id':['4321']}, {'fid':201, 'r_id':['5321']}]
I've tried below piece of code but not worked
for item in list_of_dict:
if type(item["record_id"]) == list:
item["record_id"] = [set(item["record_id"])]
please suggest me with the solution
Do:
result = [{ "fid" : d["fid"] , "r_id" : list(set(d["r_id"])) } for d in list_of_dict]
print(result)
Or simply:
for d in list_of_dict:
d["r_id"] = list(set(d["r_id"]))
print(list_of_dict)
If you really need to check the type, use isinstance:
for d in list_of_dict:
if isinstance(d["r_id"], list):
d["r_id"] = list(set(d["r_id"]))
For the canonical way of checking type in Python, read this.
If in item['r_id'] you have another type like str you can try this:
list_of_dict = [{'fid':201, 'r_id':'5321'}, {'fid':200, 'r_id':['4321', '4321']}]
for item in list_of_dict:
if type (item['r_id']) == list:
# if isinstance(item['r_id'],list):
item['r_id'] = list(set(item['r_id']))
elif type (item['r_id']) == str:
# elif isinstance(item['r_id'],str):
item['r_id'] = [item['r_id']]
#Shortest approach
>>> [{'fid' : item['fid'], 'r_id' : list(set(item['r_id'])) if type(item['r_id']) == list else [item['r_id']]} for item in list_of_dict]
[{'fid': 201, 'r_id': ['5321']}, {'fid': 200, 'r_id': ['4321']}]
You are almost there !
Though there may be other (better) solutions, your solution will also work if you change it as below:
for item in list_of_dict:
if type(item["r_id"]) == list:
item["r_id"] = list(set(item["r_id"]))
try this:
for items in list_of_dict:
temp_list = list()
if isinstance(item["r_id"], list):
for value in item["r_id"]:
if value not in templist:
temp_list.append(value)
item["r_id"] = temp_list

Filtering a list with itens with same hour and letting just one in Python

I have a list of multiple items in Python, and the list is generated randomly, this is an example:
['12:01;Jhon',
'13:25;Charlie',
'14:00;Joshua',
'12:01;Dean',
'15:04;Derek',
'14:58;George',
'12:01;Wilson',
'15:04;Marcus']
And i need to generate a new list with, picking the first item with same hour, and letting the items with different hour:
['12:01;Jhon',
'13:25;Charlie',
'14:00;Joshua',
'15:04;Derek',
'14:58;George']
Explainig the new list: Jhon was the first item with 12:01, so it is in the new list, and removing Dean and Wilson because they have also 12:01. Joshua and George contain in the list because they have different hours from the others. And Derek was the first item with 15:04, removing Marcus from the list because he have 15:04.
You can use set() to filter out the duplicates. For example:
lst = [
"12:01;Jhon",
"13:25;Charlie",
"14:00;Joshua",
"12:01;Dean",
"15:04;Derek",
"14:58;George",
"12:01;Wilson",
"15:04;Marcus",
]
out, seen = [], set()
for item in lst:
hour = item.split(";", maxsplit=1)[0]
if hour not in seen:
out.append(item)
seen.add(hour)
print(out)
Prints:
['12:01;Jhon', '13:25;Charlie', '14:00;Joshua', '15:04;Derek', '14:58;George']
Just a short dict solution:
d = {}
for s in lst:
d.setdefault(s[:5], s)
result = list(d.values())
Try it online!
This could work
x= ['12:01;Jhon', '13:25;Charlie', '14:00;Joshua', '12:01;Dean', '15:04;Derek', '14:58;George', '12:01;Wilson', '15:04;Marcus']
y = {}
for elems in x:
elems = elems.split(';')
if elems[0] not in y:y[elems[0]] = elems[1]
x = [elems2+';'+y[elems2] for elems2 in y]
print(x)
Also I suggest using a dictionary for this kind of stuff, but for your output example I turned the dict into a list
My suggestion:
We need to split up the items into lists [hour, name] and make it a dict:
items = ['12:01;Jhon', '13:25;Charlie', '14:00;Joshua', '12:01;Dean', '15:04;Derek', '14:58;George', '12:01;Wilson', '15:04;Marcus']
split_items = list(map(lambda x: x.split(';'), items))
# we need to reverse it first because dict overwrites existant keys in order
new_items_dict = dict(reversed(split_items))
# return it back to a list
new_items_list = list(new_items_dict.items())
# new_items_list == [('15:04', 'Derek'), ('12:01', 'Jhon'), ('14:58', 'George'), ('14:00', 'Joshua'), ('13:25', 'Charlie')]
# And if you want to join them back
new_items = list(map(lambda x: ';'.join(x), new_items_list))
# new_items == ['15:04;Derek', '12:01;Jhon', '14:58;George', '14:00;Joshua', '13:25;Charlie']
you can try this
new_list= []
checks = []
for i in item:
a= i.split(';')[0]
if a not in checks:
new_list.append(i)
checks.append(a)
del checks
print(new_list)

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']

adding empty string while joining the 2 lists - Python

I have 2 lists
mainlist=[['RD-12',12,'a'],['RD-13',45,'c'],['RD-15',50,'e']] and
sublist=[['RD-12',67],['RD-15',65]]
if i join both the list based on 1st element condition by using below code
def combinelist(mainlist,sublist):
dict1 = { e[0]:e[1:] for e in mainlist }
for e in sublist:
try:
dict1[e[0]].extend(e[1:])
except:
pass
result = [ [k] + v for k, v in dict1.items() ]
return result
Its results in like below
[['RD-12',12,'a',67],['RD-13',45,'c',],['RD-15',50,'e',65]]
as their is no element in for 'RD-13' in sublist, i want to empty string on that.
The final output should be
[['RD-12',12,'a',67],['RD-13',45,'c'," "],['RD-15',50,'e',65]]
Please help me.
Your problem can be solved using a while loop to adjust the length of your sublists until it matches the length of the longest sublist by appending the wanted string.
for list in result:
while len(list) < max(len(l) for l in result):
list.append(" ")
You could just go through the result list and check where the total number of your elements is 2 instead of 3.
for list in lists:
if len(list) == 2:
list.append(" ")
UPDATE:
If there are more items in the sublist, just subtract the lists containing the 'keys' of your lists, and then add the desired string.
def combinelist(mainlist,sublist):
dict1 = { e[0]:e[1:] for e in mainlist }
list2 = [e[0] for e in sublist]
for e in sublist:
try:
dict1[e[0]].extend(e[1:])
except:
pass
for e in dict1.keys() - list2:
dict1[e].append(" ")
result = [[k] + v for k, v in dict1.items()]
return result
You can try something like this:
mainlist=[['RD-12',12],['RD-13',45],['RD-15',50]]
sublist=[['RD-12',67],['RD-15',65]]
empty_val = ''
# Lists to dictionaries
maindict = dict(mainlist)
subdict = dict(sublist)
result = []
# go through all keys
for k in list(set(list(maindict.keys()) + list(subdict.keys()))):
# pick the value from each key or a default alternative
result.append([k, maindict.pop(k, empty_val), subdict.pop(k, empty_val)])
# sort by the key
result = sorted(result, key=lambda x: x[0])
You can set up your empty value to whatever you need.
UPDATE
Following the new conditions, it would look like this:
mainlist=[['RD-12',12,'a'], ['RD-13',45,'c'], ['RD-15',50,'e']]
sublist=[['RD-12',67], ['RD-15',65]]
maindict = {a:[b, c] for a, b, c in mainlist}
subdict = dict(sublist)
result = []
for k in list(set(list(maindict.keys()) + list(subdict.keys()))):
result.append([k, ])
result[-1].extend(maindict.pop(k, ' '))
result[-1].append(subdict.pop(k, ' '))
sorted(result, key=lambda x: x[0])
Another option is to convert the sublist to a dict, so items are easily and rapidly accessible.
sublist_dict = dict(sublist)
So you can do (it modifies the mainlist):
for i, e in enumerate(mainlist):
data: mainlist[i].append(sublist_dict.get(e[0], ""))
#=> [['RD-12', 12, 'a', 67], ['RD-13', 45, 'c', ''], ['RD-15', 50, 'e', 65]]
Or a one liner list comprehension (it produces a new list):
[ e + [sublist_dict.get(e[0], "")] for e in mainlist ]
If you want to skip the missing element:
for i, e in enumerate(mainlist):
data = sublist_dict.get(e[0])
if data: mainlist[i].append(data)
print(mainlist)
#=> [['RD-12', 12, 'a', 67], ['RD-13', 45, 'c'], ['RD-15', 50, 'e', 65]]

Categories