Ignoring a value in a list search - python

I am using lists to store attributes and this problem cropped up when I was searching for equal items:
l = [['a',1,2],['b',1,2],['c',2,3],['d',1,2]]
if [any,1,2] in l:
print ('blue')
elif [any,2,3] in l:
print('red')
desired output
blue
What I want is the first value being ignored/can be any value.
I know the any function doesn't work this way but what is the correct method to doing so?
Perhaps this is more understandable
l = [['a',1,2],['b',1,2],['c',2,3],['d',1,2]]
for a in range(0,4):
if [1,2] == x[1:] for x in l:
print ('blue')
elif [2,3] == x[1:] for x in l:
print('red')

For filtering equal items (according to your definition) you can use list comprehension and slicing:
>>> lst = [['a',1,2],['b',1,2],['c',2,3],['d',1,2]]
>>> [e for e in lst if e[1:] == [1,2]]
[['a', 1, 2], ['b', 1, 2], ['d', 1, 2]]

:D actually managed to do it in one line thanks to pkacprzak.
l = [['a',1,2],['b',1,2],['c',2,3],['d',1,2]]
if any(True for x in l if x[1:] == [1,2]):
print ('blue')
elif any(True for x in l if x[1:] == [2,3]):
print('red')
Code works like this:
True for x in l
iterates over l (<---this is the letter L btw) and returns True if the next bit is True
if x[1:] == [1,2]
this checks all values of x except the first and returns True
any(...)
finds if any of the values returned from the bit inside the any is True
You could also return the value of the first item like so
[x[0] for x in l if x[1:] == [1,2]]
and iterate over that as well

for completely generic case simply introduce some magical symbol to denote 'any' like '*' and write your own simple comparator
def matches(element, mask):
for el, mask_el in zip(element, mask):
if mask_el != '*' and el != mask_el:
return False
return True
and now you can do
for list_el in list:
if matches(list_el, ['*', 1, 2]):
print 'blah'
the nice thing is that it is very generic, and will work with arbitrary number of '*' in your mask.

Related

Comparing between entries in a list of lists using correct indexes

I have a list of lists and I'm trying to compare the entries in an inner list to the others.
eg: the list is my_list = [[4,6,4,3], [4,5,5,3], [4,1,1,3]]
The output I wish to get is [4,'x','x',3]
That is, if the entry in the i index in an inner list is the same across all inner lists I return the entry else I return 'x'.
I have trouble with the indexes in my code since for the i=2 round of the loop I get rows[4][j] and this is out of index. I'm generally not sure about the outer loop here or how to fix the indexes in the condition.
def my_function(my_list):
lst = []
for i, entry in enumerate(my_list):
for j, elem in enumerate(entry):
if my_list[i][j] == my_list[i+1][j] and my_list[i+1][j] == my_list[i+2][j]:
lst.append(my_lists[i][j])
else:
lst.append('x')
return lst
You should avoid manipulating indices as much as possible. To iterate on multiple lists, use zip.
To test if all values in a list are equal, you can create a set, and check if it contains only one value.
my_list = [[4,6,4,3], [4,5,5,3], [4,1,1,3]]
out = [zipped[0] if len(set(zipped)) == 1 else 'X' for zipped in zip(*my_list)]
print(out)
# [4, 'X', 'X', 3]
You can use numpy + list comprehension for that purpose:
import numpy as np
my_list = np.array([[4,6,4,3], [4,5,5,3], [4,1,1,3]])
res=['x' if (len(set(my_list[:,i]))>1) else list(set(my_list[:,i]))[0] for i in range(my_list.shape[1])]
Output:
[4, 'x', 'x', 3]
And to fix your code (I'm not sure what you meant by your if statement)
def my_function(my_list):
lst = my_list[0]
for i, entry in enumerate(my_list):
for j, elem in enumerate(entry):
if my_list[i][j]==lst[j]:
lst[j]=my_list[i][j]
else:
lst[j]='x'
return lst
You can use this simple python code.
my_list = [[4,6,4,3], [4,5,5,3], [4,1,1,3]]
li = []
for i, j, k in zip(*my_list):
val = i if i == j == k else 'x'
li.append(val)
print(li)
OUTPUT :
[4, 'x', 'x', 3]
You can also use all for checking this:
[i[0] if all(j == i[0] for j in i) else 'X' for i in(zip(*my_list))]
or:
[i[0] if all(map(lambda j: j == i[0], i )) else 'X' for i in(zip(*my_list))]
You can also extend an item to see:
[i[0] if [i[0]]*len(i) == list(i) else 'X' for i in(zip(*my_list))]
But I think the best way is to use set:
[i[0] if len(set(i))==1 else 'X' for i in(zip(*my_list))]

Checking if first digit in each element in list are the same

How would I check if the first digits in each element in a list are the same?
for i in range(0,len(lst)-1):
if lst[i] == lst[i+1]:
return True
I know that this checks for if the number before is equal to the next number in the list, but I just want to focus on the first digit.
You can use math.log10 and floor division to calculate the first digit. Then use all with a generator expression and zip to test adjacent elements sequentially:
from math import log10
def get_first(x):
return x // 10**int(log10(x))
L = [12341, 1765, 1342534, 176845, 1]
res = all(get_first(i) == get_first(j) for i, j in zip(L, L[1:])) # True
For an explanation of how this construct works, see this related answer. You can apply the same logic via a regular for loop:
def check_first(L):
for i, j in zip(L, L[1:]):
if get_first(i) != get_first(j):
return False
return True
res = check_first(L) # True
Use all() as a generator for the first character(s) of your numbers:
>>> l = [1, 10, 123]
>>> all(str(x)[0] == str(l[0])[0] for x in l)
True
The list comprehension
>>> [str(x)[0] for x in l]
creates a list
['1', '1', '1']
which sounds as if this should be enough. But all processes boolean values, and the boolean value of a string is always True, except when the string is empty. That means that it would also consider ['1','2','3'] to be True. You need to add a comparison against a constant value -- I picked the first item from the original list:
>>> [str(x)[0] == str(l[0])[0] for x in l]
[True, True, True]
whereas a list such as [1,20,333] would show
['1', '2', '3']
and
[True, False, False]
You can adjust it for a larger numbers of digits as well:
>>> all(str(x)[:2] == str(l[0])[:2] for x in l)
False
>>> l = [12,123,1234]
>>> all(str(x)[:2] == str(l[0])[:2] for x in l)
True
You could do something like this:
lst = [12, 13, 14]
def all_equals(l):
return len(set(e[0] for e in map(str, l))) == 1
print all_equals(lst)
Output
True
Explanation
The function map(str, l) converts all elements in the list to string then with (e[0] for e in map(str, l)) get the first digit of all the elements using a generator expression. Finally feed the generator into the set function this will remove all duplicates, finally you have to check if the length of the set is 1, meaning that all elements were duplicates.
For a boolean predicate on a list like this, you want a solution that returns False as soon as a conflict is found -- solutions that convert the entire list just to find the first and second item didn't match aren't good algorithms. Here's one approach:
def all_same_first(a):
return not a or all(map(lambda b, c=str(a[0])[0]: str(b)[0] == c, a[1:]))
Although at first glance this might appear to violate what I said above, the map function is lazy and so only hands the all function what it needs as it needs it, so as soon as some element doesn't match the first (initial-digit-wise) the boolean result is returned and the rest of the list isn't processed.
Going back to your original code:
this checks for if the number before is equal to the next
number in the list
for i in range(0,len(lst)-1):
if lst[i] == lst[i+1]:
return True
This doesn't work, as you claim. To work properly, it would need to do:
for i in range(0, len(lst) - 1):
if lst[i] != lst[i + 1]:
return False
return True
Do you see the difference?

Python multiple loops

A = [[[1,2,3],[4]],[[1,4],[2,3]]]
Here I want to find lists in A which sum of all sublists in list not grater than 5.
Which the result should be [[1,4],[2,3]]
I tried a long time to solve this problem in python. But I still can't figure out the right solution, which I stuck at loop out multiple loops. My code as follows, but its obviously wrong, how to correct it?
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
z = []
for l in A:
for list in l:
sum = 0
while sum < 5:
for i in list:
sum+=i
else:
break
else:
z.append(l)
print z
Asking for help~
Simplification of #KindStranger method in a one-liner:
>> [sub for x in A for sub in x if max(sum(sub) for sub in x) <= 5]
[[1, 4], [2, 3]]
A simple solution which you can think of would be like this -
A = [[[1,2,3],[4]],[[1,4],[2,3]]]
r = [] # this will be our result
for list in A: # Iterate through each item in A
f = True # This is a flag we set for a favorable sublist
for item in list: # Here we iterate through each list in the sublist
if sum(item) > 5: # If the sum is greater than 5 in any of them, set flag to false
f = False
if f: # If the flag is set, it means this is a favorable sublist
r.append(list)
print r
But I'm assuming the nesting level would be the same. http://ideone.com/hhr9uq
This should work for your problem:
>>> for alist in A:
... if max(sum(sublist) for sublist in alist) <= 5:
... print(alist)
...
[[1, 4], [2, 3]]
The one with all()
[t for item in A for t in item if all(sum(t)<=5 for t in item)]

Function that takes a list of strings and returns another specific list

I need to create a function that takes a list of words and then I want to check all the strings in that list and return another list of strings where the string first and last character are the same.
For example, given input_list = ['a','aa','aba','abb'] output should be ['aa','aba'].
Try the following:
def myfunc(lst):
return [item for item in lst if len(item) > 1 and item[0] == item[-1]]
>>> myfunc(['a','aa','aba','abb'])
['aa', 'aba']
>>>
Just check the length is > 1, and see if the first char x[0] is equal to the last char x[-1]:
print(list(filter(lambda x: len(x) > 1 and x[0] == x[-1], lst)))
['aa', 'aba']
Or if you want a function:
f = lambda l:list(filter(lambda x: len(x) > 1 and x[0] == x[-1], l))
print(f(lst))
The way to approach this, typically, is filtering a list, instead of seeing it as a different one, and define any function (either regular or lambda) to express what needs to be filtered on. That way your code is clear and easy to test and maintain:
filteredList = filter(lambda x: len(x) > 1 and x[0] == x[-1], myList)
#or:
def starts_and_ends_with_same_char(subject):
return len(subject) > 1 and str[0] == subject[-1]
filteredList = filter(starts_and_ends_with_same_char, myList)
Golfing a little:
>>> [s for s in lst if s[1:] and s[0] == s[-1]]
['aa', 'aba']

How to get item's position in a list?

I am iterating over a list and I want to print out the index of the item if it meets a certain condition. How would I do this?
Example:
testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
if item == 1:
print position
Hmmm. There was an answer with a list comprehension here, but it's disappeared.
Here:
[i for i,x in enumerate(testlist) if x == 1]
Example:
>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]
Update:
Okay, you want a generator expression, we'll have a generator expression. Here's the list comprehension again, in a for loop:
>>> for i in [i for i,x in enumerate(testlist) if x == 1]:
... print i
...
0
5
7
Now we'll construct a generator...
>>> (i for i,x in enumerate(testlist) if x == 1)
<generator object at 0x6b508>
>>> for i in (i for i,x in enumerate(testlist) if x == 1):
... print i
...
0
5
7
and niftily enough, we can assign that to a variable, and use it from there...
>>> gen = (i for i,x in enumerate(testlist) if x == 1)
>>> for i in gen: print i
...
0
5
7
And to think I used to write FORTRAN.
What about the following?
print testlist.index(element)
If you are not sure whether the element to look for is actually in the list, you can add a preliminary check, like
if element in testlist:
print testlist.index(element)
or
print(testlist.index(element) if element in testlist else None)
or the "pythonic way", which I don't like so much because code is less clear, but sometimes is more efficient,
try:
print testlist.index(element)
except ValueError:
pass
Use enumerate:
testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
if item == 1:
print position
for i in xrange(len(testlist)):
if testlist[i] == 1:
print i
xrange instead of range as requested (see comments).
Here is another way to do this:
try:
id = testlist.index('1')
print testlist[id]
except ValueError:
print "Not Found"
Try the below:
testlist = [1,2,3,5,3,1,2,1,6]
position=0
for i in testlist:
if i == 1:
print(position)
position=position+1
[x for x in range(len(testlist)) if testlist[x]==1]
If your list got large enough and you only expected to find the value in a sparse number of indices, consider that this code could execute much faster because you don't have to iterate every value in the list.
lookingFor = 1
i = 0
index = 0
try:
while i < len(testlist):
index = testlist.index(lookingFor,i)
i = index + 1
print index
except ValueError: #testlist.index() cannot find lookingFor
pass
If you expect to find the value a lot you should probably just append "index" to a list and print the list at the end to save time per iteration.
I think that it might be useful to use the curselection() method from thte Tkinter library:
from Tkinter import *
listbox.curselection()
This method works on Tkinter listbox widgets, so you'll need to construct one of them instead of a list.
This will return a position like this:
('0',) (although later versions of Tkinter may return a list of ints instead)
Which is for the first position and the number will change according to the item position.
For more information, see this page:
http://effbot.org/tkinterbook/listbox.htm
Greetings.
Why complicate things?
testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
if item == 1:
print position
Just to illustrate complete example along with the input_list which has searies1 (example: input_list[0]) in which you want to do a lookup of series2 (example: input_list[1]) and get indexes of series2 if it exists in series1.
Note: Your certain condition will go in lambda expression if conditions are simple
input_list = [[1,2,3,4,5,6,7],[1,3,7]]
series1 = input_list[0]
series2 = input_list[1]
idx_list = list(map(lambda item: series1.index(item) if item in series1 else None, series2))
print(idx_list)
output:
[0, 2, 6]
l = list(map(int,input().split(",")))
num = int(input())
for i in range(len(l)):
if l[i] == num:
print(i)
Explanation:
Taken a list of integer "l" (separated by commas) in line 1.
Taken a integer "num" in line 2.
Used for loop in line 3 to traverse inside the list and checking if numbers(of the list) meets the given number(num) then it will print the index of the number inside the list.
testlist = [1,2,3,5,3,1,2,1,6]
num = 1
for item in range(len(testlist)):
if testlist[item] == num:
print(item)
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
if id == 1:
print testlist[id]
I guess that it's exacly what you want. ;-)
'id' will be always the index of the values on the list.

Categories