Reputation: 5
I have two lists containing strings. I want to take each item in the base_list
and search to see if there is a match for the first 3 characters in any values from the custom list
. If there is a match, replace the original value in base_list
with the one from custom_list
. If there is no match, keep the original value.
base_list = ["abc123", "cde123", "efg456", "ghi123"]
custom_list = ["abc321", "efg654"]
Desired Output:
modified_base_list = ["abc321", "cde123", "efg654", "ghi123"]
Eventually I also want to write this new modified_base_list
as a file containing the items, one per line.
I've tried:
modified_base_list = []
for custom in custom_list:
for base in base_list:
if custom[:3] == base[:3]:
modified_base_list.append(custom)
else:
modified_base_list.append(base)
print(modified_base_list)
with open('newfile.txt', 'w') as f:
for s in modified_base_list:
f.write(s)
***EDITING QUESTION to account for lists that have 15k+ lines to find a faster way to do this.
Upvotes: 0
Views: 2576
Reputation: 13274
You can use a combination of list comprehension
and map
for this:
base_list = ["abc123", "cde123", "efg456", "ghi123"]
custom_list = ["abc321", "efg654"]
smaller_custom = [y[:3] for y in custom_list]
modified_base_list = ["**{}**".format(custom_list[smaller_custom.index(x[:3])]) if x[:3] in smaller_custom else x for x in base_list]
# ['**abc321**', 'cde123', '**efg654**', 'ghi123']
with open('output_data.txt','w') as outfile:
outfile.write("\n".join(modified_base_list))
I hope this helps.
Upvotes: 0
Reputation: 19806
Try the following with filter()
:
res = []
for i in base_list:
temp = list(filter(lambda j: j[:3] == i[:3], custom_list))
if temp:
res.append('**{}**'.format(temp.pop()))
else:
res.append(i)
Output:
>>> res
['**abc321**', 'cde123', '**efg654**', 'ghi123']
Upvotes: 0
Reputation: 387557
This is a solution that mutates the original list, replacing only those where the desired match exists:
>>> base_list = ["abc123", "cde123", "efg456", "ghi123"]
>>> custom_list = ["abc321", "efg654"]
>>> for i, x in enumerate(base_list):
for test in custom_list:
if test[:3] == x[:3]:
base_list[i] = test
break
>>> base_list
['abc321', 'cde123', 'efg654', 'ghi123']
Of course if you don’t want to modify the original list, you can create a coopy of it first using modified_base_list = base_list[:]
.
You can also follow your own idea but in that case, you have to make sure that you are primarily iterating over base_list
and won’t add items multiple times:
modified_base_list = []
for base in base_list:
found = False
for custom in custom_list:
if custom[:3] == base[:3]:
modified_base_list.append(custom)
found = True
break
if not found:
modified_base_list.append(base)
You can also use for…else
here instead of that utility variable found
:
for base in base_list:
for custom in custom_list:
if custom[:3] == base[:3]:
modified_base_list.append(custom)
break
else:
modified_base_list.append(base)
Upvotes: 1
Reputation: 41168
You could use a list comprehension containing a generator expression:
base_list = ["abc123", "cde123", "efg456", "ghi123"]
custom_list = ["abc321", "efg654"]
modified_base_list = [next((y for y in custom_list if y[:3] == x[:3]), x) for x in base_list]
# ['abc321', 'cde123', 'efg654', 'ghi123']
Note that I'm assuming if the same 3 character prefix occurs multiple times in custom_list
that you only wish to take the first instance.
Upvotes: 0