Python - How to match list elements by character to character - python

I have two list
List1 = ['hello','welcome','india','nation']
List2 = ['ind', 'nat','hellooo','welcomeeee']
i want to compare elements and print as below -
Output :
['india','nation','hello','welcome']
please suggest some optimized way.
I am having list with unspecified size in each, but it has one list elements matches another list elements, as random, i don't know the size of highest / longest possible match in any of the list.

You can use the Levenshtein distance to determine the closest match, so here is one implementation of Levenshtein:
def levenshteinDistance(s1, s2):
if len(s1) > len(s2):
s1, s2 = s2, s1
distances = range(len(s1) + 1)
for i2, c2 in enumerate(s2):
distances_ = [i2+1]
for i1, c1 in enumerate(s1):
if c1 == c2:
distances_.append(distances[i1])
else:
distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
distances = distances_
return distances[-1]
List1 = ['hello', 'welcome', 'india', 'nation']
List2 = ['ind', 'nat', 'helloooo', 'welcomeeeeee']
[min(zip(List1, [levenshteinDistance(j, i) for j in List1]), key=lambda x: x[1])[0] for i in List2]
#['india', 'nation', 'hello', 'welcome']

Similar to #AndreiDurnea's solution, you can also use a generator:
def comparer(L1, L2):
for i in L2:
for j in L1:
if (i in j) or (j in i):
yield j
List1 = ['hello','welcome','india','nation']
List2 = ['ind', 'nat','helloooo','welcomeeeeee']
res = list(comparer(List1, List2))
['india', 'nation', 'hello', 'welcome']
As per #pault's comment, itertools.product with a list comprehension may be more efficient than a generator:
from itertools import product
res = [j for i, j in product(List2, List1) if (i in j) or (j in i)]

List comprehension,
In [14]: [j for i in List2 for j in List1 if i in j or j in i]
Out[14]: ['india', 'nation', 'hello', 'welcome']

List1 = ['hello','welcome','india','nation']
List2 = ['ind', 'nat','helloooo','welcomeeeeee']
Rezult = []
for firstItem in List1:
for secondItem in List2:
if firstItem in secondItem or secondItem in firstItem:
Rezult.append(firstItem)
continue
print(Rezult)
the output for this is:
['hello', 'welcome', 'india', 'nation']
I would suggest to rename the variables:
list_1 = ['hello','welcome','india','nation']
list_2 = ['ind', 'nat','helloooo','welcomeeeeee']
rezult = []
for firstItem in list_1:
for secondItem in list_2:
if firstItem in secondItem or secondItem in firstItem:
rezult.append(firstItem)
print(rezult)

Related

How to add a new word to the string values in a list?

I have an issue with lists, I have a list lst =['ab', 'cd', 'ef']. Now I want to add a string ('are')to end of each string value of the list. I tried but it is getting added letter by letter, how to add the whole word to end of each string value in the list?
My code:
lst =['ab', 'cd', 'ef']
b = 'are'
new_list = [el1+'_'+el2 for el2 in b for el1 in lst]
It gives:
new_list = ['ab_a', 'cd_a', 'ef_a','ab_r', 'cd_r', 'ef_r','ab_e', 'cd_e', 'ef_e']
Excepted output:
new_list = ['ab_are', 'cd_are', 'ef_are']
Rather than iterate on the second string just append like
new_list = [el1+'_'+ b for el1 in lst]
Try this:
lst =['ab', 'cd', 'ef']
b = 'are'
new = ["_".join([item, b]) for item in lst]
# ['ab_are', 'cd_are', 'ef_are']
You are iterating through both list and string. Just iterate through the list:
lst =['ab', 'cd', 'ef']
b = 'are'
new_list = [el + '_' + b for el in lst]
print(new_list)
Output:
['ab_are', 'cd_are', 'ef_are']
Just iterate in list
lst = ["ab", "cd", "ef"]
b = "are"
iterated_list = [i + " " + b for i in lst]
print(iterated_list)
Another option would be the following below:
lst = ["ab", "cd", "ef"]
b = "are"
iterated_list = []
for i in lst:
iterated_list.append(i + " " + b)
print(iterated_list)

split or separate this list wherever there is an empty list `[]` using python [duplicate]

This question already has answers here:
How to split a list into sublists based on a separator, similar to str.split()?
(9 answers)
Closed 2 years ago.
I want to split or separate this list wherever there is an empty list []
Sample list:
lists = [['I'], ['speak'], ['english'], [], ['I'], ['speak'], ['spanish'], [], ['I'], ['speak'], ['Hindu']]
Desired output:
lists = [
[['I'], ['speak'],['english']],
[['I'], ['speak'],['spanish']],
[['I'], ['speak'],['Hindu']],
]
How do I achieve this?
I've tried:
new_list = []
for I in range(len(lists)):
temp_list = []
if lists[i] != []:
temp_list.append(lists [i])
new_list.append(temp_list)
You can use itertools.groupby() to achieve this as:
from itertools import groupby
my_list = [['I'], ['speak'], ['english'], [], ['I'], ['speak'], ['spanish'], [], ['I'], ['speak'], ['Hindu']]
new_list = [list(l) for i, l in groupby(my_list, bool) if i]
where new_list holds:
[
[['I'], ['speak'], ['english']],
[['I'], ['speak'], ['spanish']],
[['I'], ['speak'], ['Hindu']]
]
new_list = [[]]
for item in lists:
if item:
new_list[-1].append(item[0])
else:
new_list.append([])
result:
[['I', 'speak', 'english'], ['I', 'speak', 'spanish'], ['I', 'speak', 'Hindu']]
as you can see a way to solve the problem is this , you can use a Method that includes :
Using list comprehension + zip() + slicing + enumerate()
where you first split list into lists by particular value
size = len(test_list)
idx_list = [idx + 1 for idx, val in
enumerate(test_list) if val == 5]
and then create a new one
res = [test_list[i: j] for i, j in
zip([0] + idx_list, idx_list +
([size] if idx_list[-1] != size else []))]

Substring filter list elements by another list in Python

I have two lists looking like:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
I want to substring filter list1 by elements of list2 and get expected output as follows:
outcome = ['bj-100-cy', 'sh-200-pd']
When doing:
list1 = str(list1)
list2 = str(list2)
outcome = [x for x in list2 if [y for y in list1 if x in y]]
I get a result like this: ['[', '1', '0', '0', ',', ' ', '2', '0', '0', ']'].
How can I filter it correctly? Thanks.
Reference related:
Is it possible to filter list of substrings by another list of strings in Python?
List comprehension and any:
[i for i in list1 if any(i for j in list2 if str(j) in i)]
any to check if any element of list2 is a substring of the list1 item (__contains__) being iterated over.
Example:
In [92]: list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
...: list2 = [100, 200]
...:
In [93]: [i for i in list1 if any(i for j in list2 if str(j) in i)]
Out[93]: ['bj-100-cy', 'sh-200-pd']
You can use any:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
list2 = [str(x) for x in list2]
outcome = [s for s in list1 if any(x in s for x in list2)]
any returns True if any of the conditions you give it are True.
list1 = str(list1)
list2 = str(list2)
You are converting your list into a string with the above statements. So when you iterate in a for loop, you are iterating each characters, instead of each word.
So you should remove string conversion and instead do a list comprehension as follows.
Also, in your outcome file instead of checking if the word in list2 is in list1, you are checking the opposite. So you got like 100 and 200 as chars which are in list 2.
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
outcome = [x for x in list1 for y in list2 if str(y) in x]
You can try this one:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
outcome = []
for item in list1:
if any(str(i) in item for i in list2):
outcome.append(item)
output:
['bj-100-cy', 'sh-200-pd']
Another alternative list comprehension :
>>> list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
>>> list2 = [100, 200]
>>> occur = [i for i in list1 for j in list2 if str(j) in i]
>>> occur
['bj-100-cy', 'sh-200-pd']
You can use builtin filter method to filter the list based on your condition. Your condition requires python in operator to search for needle([100, 200]) in haystack ([['bj-100-cy','bj-101-hd',...]]).
We can use contains method to simplify search syntax.
Code
from operator import contains
filter(lambda x: any(contains(x,str(y)) for y in list2), list1)
Example
>>> list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
>>> list2 = [100, 200]
>>> for item in filter(lambda x: any(contains(x,str(y)) for y in list2), list1):
... print(item)
...
bj-100-cy
sh-200-pd
You can use regex:
import re
list1 = ['bj-100-cy', 'bj-101-hd', 'sh-200-pd', 'sh-201-hp']
list2 = [100, 200]
pattern = re.compile('|'.join(map(str, list2)))
list(filter(pattern.search, list1))
# ['bj-100-cy', 'sh-200-pd']

Conditional Merging of Lists

I'm trying to merge two lists based on the following rules:
The first element in list1 should be merged with the last element in list2, the second element in list1 should be merged with second last element in list2 and so on.
If an element in list1/list2 is None, then the corresponding element in the other list should be kept as it is in the merged list.
I feel I may have to use a linked list here, but I'm not sure. I'm trying to figure out the solution by looping over the lists, but I'm not able to figure out the logic here.
def merge_list(list1, list2):
merged_data=""
new_str=""
#write your logic here
for l1 in list1:
for l2 in list2[::-1]:
if l1 is None or l2 is None:
pass
else:
new_str = l1+l2
i=list2.index(l2)
print(new_str)
break
#return resultant_data
list1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
list2=['y','tor','e','eps','ay',None,'le','n']
merged_data=merge_list(list1,list2)
print(merged_data)
Expected Output:
“An apple a day keeps the doctor away”
You can use zip to iterate through two lists simultaneously:
def merge_list(lst1,lst2):
s = ''
for x, y in zip(lst1, lst2[::-1]):
if y and x:
s += x + y
elif x:
s += x
elif y:
s += y
s += ' '
return s[:-1]
list1 = ['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
list2 = ['y','tor','e','eps','ay',None,'le','n']
merged_data = merge_list(list1,list2)
print(merged_data)
# An apple a day keeps the doctor away
You can shorten this and use a list-comprehension, like below (but, I would prefer the other which is more readable):
def merge_list(lst1,lst2):
return ' '.join(x + y if x and y else x if x else y for x, y in zip(lst1, lst2[::-1]))
Assuming both lists have the same length
>>> list1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
>>> list2=['y','tor','e','eps','ay',None,'le','n']
>>> ' '.join([l1 + l2 if l1 and l2 else l1 if l1 and not l2 else l2 for l1, l2 in zip(list1, reversed(list2)) if l1 and l2])
'An apple a day keeps the doctor away'
Make sure the lists are in same length then just a zip is enough. But replace None value with '' (empty string)
["".join(row) for row in zip(list1, reversed(list2))]
=>
['An', 'apple', 'a', 'day', 'keeps', 'the', 'doctor', 'away']
First use list comprehensions to merge the two lists and then convert that list into string.
" ".join(str(x) for x in [list1[i]+list2[len(list2)-1-i] if list2[len(list2)-1-i] != None else list1[i] for i in range(len(list1))])
'An apple a day keeps the doctor away'
def fetch_index(list2, item_index):
x = list2[::-1]
return x[item_index]
def merge_list(list1, list2):
list_3 = []
#write your logic here
for l1 in list1:
l2 = fetch_index(list2, list1.index(l1))
if l1 is None and l2 is None:
pass
elif l1 is None:
list_3.append(l2)
elif l2 is None:
list_3.append(l1)
else:
list_3.append(l1+l2)
return(list_3)
list1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
list2=['y','tor','e','eps','ay',None,'le','n']
x = merge_list(list1,list2)
print ' '.join(i for i in x)
A longer version if you don't want to use zip
A short answer without using zip.
" ".join([list1[x]+[y if y is not None else '' for y in list2 ][::-1][x] for x in range(len(list1)-1)]
list1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
list2=['y','tor','e','eps','ay',None,'le','n']
a=list2.remove(None)
list2.insert(5,"")
list3 = [ str(x[0]) + x[1] for x in zip(list1, list2[::-1]) ]
print ' '.join(list3)
output:
An apple a day keeps the doctor away
l1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
l2=['y','tor','e','eps','ay',None,'le','n']
a=l2[::-1]
l3=[]
for i in range(len(l1)):
if(l1[i] is None or a[i] is None):
l3.append(l1[i])`enter code here`
else:
l3.append(l1[i]+a[i])
print(" ".join(l3))
def merge_list(list1, list2):
merged_data = ""
list3 = list1
for i in range(1, 2*len(list2) + 1,2): #Converting both lists in single list
list3.insert(i, list2[-1]) # Adding last elements of list2 at alternate to positions elements of list3
list2.pop() #Removing the last element from list2
list3 = ["" if i is None else i for i in list3] # Handling NoneType condition. If there is "None", convertted to ""
for i in range(0,len(list3),2):
word="".join(list3[i:i+2]) #joining the elements in set of two
merged_data=merged_data+word+" " #converting above word into one
return merged_data
list1=['A', 'app','a', 'd', 'ke', 'th', 'doc', 'awa']
list2=['y','tor','e','eps','ay',None,'le','n']
s=''
new=''
for i in list1:
for j in list2[::-1]:
if i==None:
i=''
elif j==None:
j=''
new=i+j
s=s+new+' '
list2.pop(-1)
break
print(s)

nested loop in list comprehension

I have a list of words in l that if any of it exists in the first index of each tuple in l2, remove the entire tuple.
my code:
l = ['hi', 'thanks', 'thank', 'bye', 'ok', 'yes', 'okay']
l2 = [('hi how are u', 'doing great'), ('looking for me', 'please hold')]
l3 = [k for k in l2 if not any(i in k[0] for i in l) ]
somehow the code does not work and i get back an empty list for l3.
I want
l3 = [('looking for me', 'please hold')]
Split k[0] to get a list of words:
[k for k in l2 if not any(i in k[0].split() for i in l)]
This way it checks if i matches a word exactly.
It could also be interpreted as if k[0] does not starts with any of l, then you can do this:
[k for k in l2 if not k[0].startswith(tuple(l))]
Sets make membership testing easy. Use a function to filter your list.
import operator
first = operator.itemgetter(0
l = ['hi', 'thanks', 'thank', 'bye', 'ok', 'yes', 'okay']
l2 = [('hi how are u', 'doing great'), ('looking for me', 'please hold')]
def foo(t, l = set(l)):
t = set(first(t).split())
return bool(l & t)
l3 = [thing for thing in l2 if not foo(thing)]

Categories