Related
I have a list that looks like this
lst = ['a','b','43.23','c','9','22']
I would like to remove the elements that cannot be represented as floats and hence I am doing the following (Attempt 1):
for i,j in enumerate(lst):
try:
lst[i]=float(j)
except:
lst.remove(j)
Which leaves the list looking like this
lst = ['b', 43.23, '9', 22.0]
whereas what I need is this
lst = [43.23, 9.0 , 22.0]
And so I'm doing the following:
for i,j in enumerate(lst):
try:
lst[i]=float(j)
except:
pass
lst = [i for i in lst if type(i) != str]
Is there a cleaner way to do this.?
EDIT: Changed the name of example list from 'list' to 'lst' based on the recommendations below.
You can use the following function from this stackoverflow post:
def isfloat(value):
try:
float(value)
return True
except ValueError:
return False
And, then use it in a list comprehension:
>>> l = ['a','b','43.23','c','9','22']
>>> [float(x) for x in l if isfloat(x)]
# [43.23, 9.0, 22.0]
First you shouldn't name your variable list it will shadow the built-in list function/class. You can use a simple function to do this:
>>> lst = ['a','b','43.23','c','9','22']
>>> def is_float(el):
... try:
... return float(el)
... except ValueError:
... pass
...
>>> [i for i in lst if is_float(i)]
['43.23', '9', '22']
>>> [float(i) for i in lst if is_float(i)] # to return a list of floating point number
[43.23, 9.0, 22.0]
The problem with your code is that you are trying to modify your list while iterating. Instead you can make a copy of your list then use the element index to remove their value.
lst = ['a','b','43.23','c','9','22']
lst_copy = lst.copy()
for el in lst:
try:
float(val)
except ValueError:
lst_copy.remove(el)
Of course this is less efficient than the solution using the list comprehension with a predicate because you first need to make a copy of your original list.
You shouldn't manipulate the list you're iterating through (and you shouldn't call it list neither, since you would shadow the built-in list), since that messes up with the indexes.
The reason why 'b' shows up in your output is that during the first iteration, 'a' is not a float, so it gets removed. Thus your list becomes:
['b','43.23','c','9','22']
and b becomes list[0]. However, the next iteration calls list[1] skipping thus 'b'.
To avoid such an issue, you can define a second list and append the suitable values to that:
l1 = ['a','b','43.23','c','9','22']
l2 = []
for item in l1:
try:
l2.append(float(item))
except ValueError: # bare exception statements are bad practice too!
pass
Would be better in considering iterators to efficiently use system memory. Here is my take to the solution.
def func(x):
try:
return float(x)
except ValueError:
pass
filter(lambda x: x, map(func, li))
Borrowing idea from this post : python: restarting a loop, the first attempt can be fixed with a simple while loop
lst = ['a','b','43.23','c','9','22']
temp = 0
while temp<len(lst):
try:
lst[temp] = float(lst[temp])
temp+=1
except ValueError:
lst.remove(lst[temp])
temp = 0
which leaves me with the desired result (by resetting the loop iterator)
lst = [43.23, 9.0 , 22.0]
I'm looking for a clean way to check if an item is member of a list of objects.
Basically this is what I want to do:
class Constant:
def __init__(self,name,value):
self.name = name
self.value = value
list = [Constant('el1',1),Constant('el2',2)]
list2= ['el4','el5','el1']
for item in list2:
#clean solution for this if clause is needed (I'm aware list.name triggers an error)
if item in list.name:
print 'it is a member'
So it is important to me that the item matches only on the name, the value has no meaning when searching. I know I can solve this by adding an additional for loop like this:
for item in list2:
for itemConstant in list:
if item == itemConstant.name:
print 'it is a member'
But I want to be sure there is no better solution than this.
You can use any:
for item in list2:
if any(item == c.name for c in list):
print 'it is a member'
Since the value has no meaning use a set with in as strings are hashable and you will have a 0(1) lookups, storing the names from the instances in a set:
st = {Constant('el1',1).name,Constant('el2',2).name}
lst2 = ['el4','el5','el1']
for c in lst2:
if c in st:
print('it is a member')
Or make lst2 a set:
lst = [Constant('el1',1), Constant('el2',2)]
st = {'el4','el5','el1'}
for c in lst:
if c.name in st:
print(c.name)
I presume you want exact matches as "foo" in "foobar" would be True.
You can also leave the original list as is an create a set from the instance names:
lst = [Constant('el1', 1), Constant('el2', 2)]
lst2 = ['el4', 'el5', 'el1']
st = {c.name for c in lst}
for c in lst2:
if c in st:
print('it is a member')
So you still have an 0(n) solution as it just requires one more pass over your instances lst.
Make list2 a set and loop over your list of constants to test each against that set. Use the any() callable to exit early when a match is found:
constants = [Constant('el1', 1), Constant('el2',2)]
elements = {'el4', 'el5', 'el1'}
if any(c.name in elements for c in constants):
print 'is a member'
This reduces the problem to one loop; membership testing against a set is a O(1) constant time operation on average. The loop is exited early when a match is found, further reducing the number of tests made.
I'm new to python and trying to make a function Uniqueify(L) that will be given either a list of numbers or a list of strings (non-empty), and will return a list of the unique elements of that list.
So far I have:
def Uniquefy(x):
a = []
for i in range(len(x)):
if x[i] in a == False:
a.append(x[i])
return a
It looks like the if str(x[i]) in a == False: is failing, and that's causing the function to return a empty list.
Any help you guys can provide?
Relational operators all have exactly the same precedence and are chained. This means that this line:
if x[i] in a == False:
is evaluated as follows:
if (x[i] in a) and (a == False):
This is obviously not what you want.
The solution is to remove the second relational operator:
if x[i] not in a:
You can just create a set based on the list which will only contain unique values:
>>> s = ["a", "b", "a"]
>>> print set(s)
set(['a', 'b'])
The best option here is to use a set instead! By definition, sets only contain unique items and putting the same item in twice will not result in two copies.
If you need to create it from a list and need a list back, try this. However, if there's not a specific reason you NEED a list, then just pass around a set instead (that would be the duck-typing way anyway).
def uniquefy(x):
return list(set(x))
You can use the built in set type to get unique elements from a collection:
x = [1,2,3,3]
unique_elements = set(x)
You should use set() here. It reduces the in operation time:
def Uniquefy(x):
a = set()
for item in x:
if item not in a:
a.add(item)
return list(a)
Or equivalently:
def Uniquefy(x):
return list(set(x))
If order matters:
def uniquefy(x):
s = set()
return [i for i in x if i not in s and s.add(i) is None]
Else:
def uniquefy(x):
return list(set(x))
I have a list of lists in my Python 3:
mylist = [[a,x,x][b,x,x][c,x,x]]
(x is just some data)
I have my code which does that:
for sublist in mylist:
if sublist[0] == a:
sublist[1] = sublist[1]+1
break
now I want to add an entry, if there is any sublistentry ==a
How can I do that?
Use any() to test the sublists:
if any(a in subl for subl in mylist):
This tests each subl but exits the generator expression loop early if a match is found.
This does not, however, return the specific sublist that matched. You could use next() with a generator expression to find the first match:
matched = next((subl for subl in mylist if a in subl), None)
if matched is not None:
matched[1] += 1
where None is a default returned if the generator expression raises a StopIteration exception, or you can omit the default and use exception handling instead:
try:
matched = next(subl for subl in mylist if a in subl)
matched[1] += 1
except StopIteration:
pass # no match found
You could use any() with list comprehensions (well, generator comprehensions here):
inList = any(a in sublist for sublist in mylist)
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.