Search for a char in list of lists - python

I have a list of lists, and I want to return those sublists that have a specific char.
If the list is:
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
I want to retrive ['g', 'j'] "or it's position" if I search using j or g

Try this:-
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def search(search_char):
result = [x for x in lst if search_char in x]
return result
print(search('g'))

For a start there is a keyword error in your variable - list is a keyword, try my_list.
This works for returning the list you want:
#Try this
my_list = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def check_for_letter(a_list,search):
for i in a_list[:]:
if search in a_list[0]:
return a_list[0]
else:
a_list[0] = a_list[1]
Session below:
>>> check_for_letter(my_list,"j")
['g', 'j']
>>>

This is one way. It works even for repeats.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def searcher(lst, x):
for i in range(len(lst)):
if x in lst[i]:
yield i
list(searcher(lst, 'g')) # [1]
list(map(lst.__getitem__, searcher(lst, 'g'))) # [['g', 'j']]

lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
spec_char = input("What character do you want to find?: ")#ask for a character to find
def find_char(spec_char):
for list_count, each_list in enumerate(lst): #iterates through each list in lst
if spec_char in each_list: #checks if specified character is in each_list
return spec_char, lst[list_count] #returns both the character and list that contains the character
def main(): #good habit for organisation
print(find_char(spec_char)) #print the returned value of find_char
if __name__ == '__main__':
main()

lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
def search(spec_char):
for subList in lst:
if spec_char in subList:
return subList
return False
print search('g')
>>> ['g', 'j']

y=[['a','b'],['c','d'],['e','f'],['f']]
result=[x for x in y if 'f' in x])
here I took 'f' as the character to be searched

Alternatively, we can also use the lambda and the filter functions.
The basics for lambda and filter function can be found in python documentation.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']]
ch = input('Enter the character') # or directly type the character in ''
# lambda <parameter to the function>: <value to be returned>
# filter(<lambda function to check for the condition>, <sequence to iterate over>)
r = list(filter(lambda lst: ch in lst,lst))
print(r)
Note: To see the value returned by the lambda and the filter functions, I am storing the result in a list and printing the final output.

Below is the solution and explanation for your question. Please view the image at the bottom of this answer for further clarification and to view the output.
lst = [['a', 'e'], ['g', 'j'], ['m', 'n', 'w'], ['z']] #So this is your list
character=input("Enter the character: ") #The character you are searching for
for a in lst: #it means that variable [a] is an item in the list [lst]
for b in a: #it means that variable [b] is an item in the list [a]
if(b==character): #To check if the given character is present in the list
print(a) #Finally to print the list in which the given character is present
So, the code part is over. Now, let's look what the output will be.
C:\Users\User\Desktop\python>coc.py
Enter the character: a
['a', 'e']
C:\Users\User\Desktop\python>coc.py
Enter the character: w
['m', 'n', 'w']
Click here to view the image of my code and output

Related

Python recursion systematic ordering

I wrote my code and it's working perfectly but the output doesn't really look good. I was it to look more presentable/systematic. How do I do that? This is the kind of result I'm currently getting:
and this is the type of result I want:
This code is basically to find permutations of whatever is inputted.
def permutations(aSet):
if len(aSet) <= 1: return aSet
all_perms = []
first_element = aSet[0:1]
subset = aSet[1:]
partial = permutations(subset)
for permutation in partial:
for index in range(len(aSet)):
new_perm = list(permutation[:index])
new_perm.extend(first_element)
new_perm.extend(permutation[index:])
all_perms.append(new_perm)
return all_perms
I can't figure out what to try.
You can sort the output array with a custom key function. Here keyFunc converts a permutaiton (list of characters) into a single string to perform lexicographic sorting.
from pprint import pprint
# insert your function here
def keyFunc(char_list):
return ''.join(char_list)
chars = list('dog')
permutation = permutations(chars)
permutation.sort(key=keyFunc)
pprint(permutation)
Output:
[['d', 'g', 'o'],
['d', 'o', 'g'],
['g', 'd', 'o'],
['g', 'o', 'd'],
['o', 'd', 'g'],
['o', 'g', 'd']]
Here's a way to order the permutations differently: for each item in the input array, take it out of the array, find all permutations of the remaining subarray, then prepend this item to each permutation of this subarray. This has the effect of placing permutations with similar prefixes together.
from pprint import pprint
def permutations2(chars):
if len(chars) <= 1: return [chars]
all_perms = []
for idx, char in enumerate(chars):
subarr = chars[:idx] + chars[idx+1:]
subperms = permutations2(subarr)
for subperm in subperms:
new_perm = [char] + subperm
all_perms.append(new_perm)
return all_perms
chars = list('dog')
pprint(permutations2(chars))
Result:
[['d', 'o', 'g'],
['d', 'g', 'o'],
['o', 'd', 'g'],
['o', 'g', 'd'],
['g', 'd', 'o'],
['g', 'o', 'd']]

Removes duplicates from nested list without use of set

I have a list of lists and I want to remove duplicates within each nested list.
Input: [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
Output: [['c', 'p'], ['a'], ['t','p']]
The key here is that I cannot use the set() function or fromkeys().
Here is the code I have,
ans = []
for i in letters:
[ans.append([x]) for x in i if x not in ans]
which returns
[['c'], ['p'], ['p'], ['a'], ['a'], ['a'], ['t'], ['t'], ['p']]
which isn't what I want.
You tripped yourself up with the nested lists. A second loop is necessary to filter the elements. Although it's quite inefficient, you can write your attempt as
ans = []
for i in letters:
k = []
for j in i:
if j not in k:
k.append(j)
ans.append(k)
You can likely shorten this code, but not reduce its complexity.
To do that, you can use something sorted and itertools.groupby. this is still less efficient than a hash table, but better than linear lookup (although it likely doesn't matter much for short arrays):
ans = [[k for k, _ in groupby(sorted(i))] for i in letters]
You can iterate over the inner list and check if that character is already present or not
inputList = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
result = []
for l in inputList:
# create a empty list to store intermediate result
tmp = []
# iterate over sublist
for ch in l:
if ch not in tmp: tmp.append(ch)
result.append(tmp)
print(result)
Since you can't use set() or fromkeys(), I would suggest a normal loop iteration, each time checking if value is already present:
lst = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
new_lst = []
for x in lst:
res = []
for y in x:
if y not in res:
res.append(y)
new_lst.append(res)
print(new_lst)
Ideally, new_lst here should be a set.
list=[['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
ans=[]
for sublist in list:
temp=[]
for ch in sublist:
if ch not in temp:
temp.append(ch)
ans.append(temp)
print(ans)
#I think it should work, very simple, it could be more complex
Just ignore every instance of a letter until it is the last one.
for every sublist of input:[[...] for sub in input]
store the letter if it isn't in the rest of the sublist:[ltr for i, ltr in enumerate(sub) if ltr not in sub[i+1:]]
Put it together and you have:
input = [['c', 'p', 'p'], ['a', 'a', 'a'], ['t', 't', 'p']]
output = [[ltr for i, ltr in enumerate(sub) if ltr not in sub[i+1:]] for sub in input]
print(output) #[['c', 'p'], ['a'], ['t', 'p']]

Remove characters from a list with for loop [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 2 years ago.
I'm having trouble understanding how 'for loop' works in Python. I want to remove a character from a list using for loop to iterate through the list but the output is not as expected.
In the following code I want to remove the character 'e':
lista = ['g', 'e', 'e', 'k', 'e','s', 'e', 'e']
for x in lista:
if x == 'e':
lista.remove(x)
print(lista)
It prints ['g', 'k', 's', 'e', 'e'] when I was expecting ['g', 'k', 's'].
Thank you.
You cannot remove things from a list when you iterate over it. This is because when you remove an item from the list it shrinks. So what's happening is that when you encounter an 'e', the list is shrunk and you go to the next item in the list. But since the list shrunk, you're actually jumping over an item.
To solve your problem, you have to iterate over copy of your list.
lista = ['g', 'e', 'e', 'k', 'e','s', 'e', 'e']
for x in lista.copy():
if x == 'e':
lista.remove(x)
print(lista)
You can use the following code
lista = ['g', 'e', 'e', 'k', 'e','s', 'e', 'e']
for i in range(0, len(lista)):
element = lista[i]
if element == 'e':
del lista[i]
The above approach will modify the original list.
A far more simpler and better way is as follows:
list(filter(('e').__ne__, lista))
Both the methods return
['g', 'k', 's']
A solution to your problem may be this :
while 1:
try:
lista.remove("e")
except ValueError:
break
The simple list comprehension. The idea is to not update the list while iterating.
lista = ['g', 'e', 'e', 'k', 'e','s', 'e', 'e']
lista = [i for i in lista if i!='e']
I think the most pythonic way is to do it using list comprehension as shown below:
lista = ['g', 'e', 'e', 'k', 'e','s', 'e', 'e']
lista = [x for x in lista if x != 'e']
print(lista)
The reason why your method is not working is because you cannot remove items from a list whilst iterating over it, as you will be changing the indexes of each object in the list.
When you remove an item from a List it gets updated. Therefore shrinking it.
Thus, in your case when first two of the e's are removed, last two elements are not taken into consideration.
What you need to do is to check if the the element still exists-
lista = ['g', 'e', 'e', 'k', 'e', 's', 'e', 'e']
while 'e' in lista:
lista.remove('e')
print(lista)
UPDATE:
As #mad_ pointed out, you can reduce the complexity by-
lista = ['g', 'e', 'e', 'k', 'e', 's', 'e', 'e']
print([i for i in lista if i != 'e'])

How to group similar sequence preserving order in Python? [duplicate]

This question already has an answer here:
How can I group equivalent items together in a Python list?
(1 answer)
Closed 3 years ago.
I want to split a list sequence of items in Python or group them if they are similar.
I already found a solution but I would like to know if there is a better and more efficient way to do it (always up to learn more).
Here is the main goal
input = ['a','a', 'i', 'e', 'e', 'e', 'i', 'i', 'a', 'a']
desired_ouput = [['a','a'], ['i'], ['e','e', 'e'], ['i', 'i'], ['a', 'a']
So basically I choose to group by similar neighbour.I try to find a way to split them if different but get no success dooing it.
I'm also keen on listening the good way to expose the problem
#!/usr/bin/env python3
def group_seq(listA):
listA = [[n] for n in listA]
for i,l in enumerate(listA):
_curr = l
_prev = None
_next= None
if i+1 < len(listA):
_next = listA[i+1]
if i > 0:
_prev = listA[i-1]
if _next is not None and _curr[-1] == _next[0]:
listA[i].extend(_next)
listA.pop(i+1)
if _prev is not None and _curr[0] == _prev[0]:
listA[i].extend(_prev)
listA.pop(i-1)
return listA
listA = ['a','a', 'i', 'e', 'e', 'e', 'i', 'i', 'a', 'a']
output = group_seq(listA)
print(listA)
['a', 'a', 'i', 'e', 'e', 'e', 'i', 'i', 'a', 'a']
print(output)
[['a', 'a'], ['i'], ['e', 'e', 'e'], ['i', 'i'], ['a', 'a']]
I think itertool.groupby is probably the nicest way to do this. It's flexible and efficient enough that it's rarely to your advantage to re-implement it yourself:
from itertools import groupby
inp = ['a','a', 'i', 'e', 'e', 'e', 'i', 'i', 'a', 'a']
output = [list(g) for k,g in groupby(inp)]
print(output)
prints
[['a', 'a'], ['i'], ['e', 'e', 'e'], ['i', 'i'], ['a', 'a']]
If you do implement it yourself, it can probably be much simpler. Just keep track of the previous value and the current list you're appending to:
def group_seq(listA):
prev = None
cur = None
ret = []
for l in listA:
if l == prev: # assumes list doesn't contain None
cur.append(l)
else:
cur = [l]
ret.append(cur)
prev = l
return ret

Python: Get all combinations of sequential elements of list

Given an array say x = ['A','I','R']
I would want output as an
[['A','I','R'],['A','I'],['I','R'],['A'],['I'],['R']]
What I don't want as output is :
[['A','I','R'],['A','I'],['I','R'],['A','R'],['A'],['I'],['R']] # extra ['A','R'] which is not in sequence .
Below is the code which gives the output I don't want:
letter_list = [a for a in str]
all_word = []
for i in xrange(0,len(letter_list)):
all_word = all_word + (map(list, itertools.combinations(letter_list,i))) # dont use append. gives wrong result.
all_word = filter(None,all_word) # remove empty combination
all_word = all_word + [letter_list] # add original list
My point is I only want combinations of sequences. Is there any way to use itertools or should I write custom function ?
Yes, you can use itertools:
>>> x = ['A', 'I', 'R']
>>> xs = [x[i:j] for i, j in itertools.combinations(range(len(x)+1), 2)]
>>> xs
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
>>> sorted(xs, key=len, reverse=True)
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Credit: answer by hochl
Try to use yield:
x = ['A','I','R']
def groupme(x):
s = tuple(x)
for size in range(1, len(s) + 1):
for index in range(len(s) + 1 - size):
yield list(x[index:index + size])
list(groupme(x))
>>> [['A'], ['I'], ['R'], ['A', 'I'], ['I', 'R'], ['A', 'I', 'R']]
don't try to be so magical: two loops will do what you want; one over possible sequence starts, the inner over possible sequence lengths:
x = "AIR" # strings are iterables/sequences, too!
all_words = []
for begin in xrange(len(x)):
for length in xrange(1,len(x) - begin+1):
all_words.append(x[begin:begin+length])
using list comprehension:
letters=['A', 'I', 'R']
[letters[start:end+1]
for start in xrange(len(letters))
for end in xrange(start, len(letters))]
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
if it is important to have the order you proposed (from longest to shortest and when the same length by starting position) you can do instead:
[letters[start:start+l+1]
for l in range(len(letters))[::-1]
for start in xrange(len(letters)-l)]
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Just to address Holroy comment. If instead of using list comprehension you use a generator expression (just substituting external [] with ()) you would get a much less memory requiring code. But in this case you must be careful of not using the result more than once or for instance not trying to use list methods (such as len, or removing elements) on the result.

Categories

Resources