check that x in list.remove(y) in one line - python

What is the way to make list.remove() behave as a list on this same line to perform operations such as element searches or indexing (i.e. make iterable or subscriptable)? E.g. I am trying the above which are not working.
myList = ['a', 'b', 'c']
'a' in myList.remove('b')
'a' in list(myList.remove('c'))
Error:
Traceback (most recent call last):
File "<pyshell#83>", line 1, in <module>
'a' in list(myList.remove('c'))
TypeError: 'NoneType' object is not iterable
Edit after first responses.
What I am trying to do is the following.
myList = ['a', 'b', 'c']
if 'a' in myList:
myList.remove('b')
if 'c' in myList:
...
So I am wondering if I could this in the same statement

Hope this will do
if 'a' in your_list and 'c' in set(your_list) - {'b'}:
# some code
pass
I am using sets here. Note that after the statement 'b' still will be in the list.
But from a logical point of view I prefer to test for this
{'a', 'c'} <= set(your_list) and 'b' != 'c'

remove edits the list in place and returns None, so what you're doing won't work. You need a function that returns a new list with that element removed. If you really need a one-liner:
'a' in [x for x in myList if x is not 'b']

list.remove() function does not return anything.
So you can check in two steps:
myList = ['a', 'b', 'c']
myList.remove('b')
if 'a' in myList:
#Some logic

you can quickly check if b is in the list and remove it first
myList.remove('b') if 'b' in myList else None
then using:
'a' in myList
To check if 'a' is in the list (with remove 'b')

Related

Is it possible to use map on methods like List.append

I am wondering if you can use mapping like this:
x = ["a"]
y = ["b","c","d"]
map(x.append,y)
I would like x = ["a","b","c","d"], However this does not happen
map returns an iterator, so nothing happens as long as you don't iterate on it. You could make that happen by calling list on it:
x = ["a"]
y = ["b","c","dx"]
list(map(x.extend,y))
# [None, None, None]
print(x)
# ['a', 'b', 'c', 'd', 'x']
Note that, as extend expects an iterable (which str objects are), it will iterate on each string in y and append the characters, so you'll get 'd' and 'x' in the example above.
You probably meant to use append:
x = ["a"]
y = ["b","c","dx"]
list(map(x.append,y))
# [None, None, None]
print(x)
# ['a', 'b', 'c', 'dx']
But anyway, map is meant to yield the results of applying the function to the items of the iterable (here, the None returned by x.append()), and using it for the side effect of the function makes things rather unclear.
x = ["a"]
y = ["b","c","d"]
x.extend(y)
print (x)
output:
['a', 'b', 'c', 'd']
The extend() extends the list by adding all items of a list (passed as an argument) to the end.
The syntax of extend() method is:
list1.extend(list2)
Here, the elements of list2 are added to the end of list1.
Extend function takes a list as input as I know. With map() it would try to take an element, since map gives elements of an iterable to a function one by one and returns the result as a list again.
This should do
x.extend(y)
Any reason for doing this?
map is a worst choice in case of readability and execution speed.
x = ["a"]
y = ["b","c","d"]
x.extend(y)

if any(x in str for x in a): what's x when true

This post gets me half way to where I want to go. I'd like to know which string the following code found, but on my machine it isn't working:
a = ['a', 'b', 'c']
str = "a123"
if any(x in str for x in a):
print x
This produces the error: "NameError: name 'x' is not defined". How does one determine which string (within a) was found? In other words, based on which string was found in the list, I want to do something specific in the code that follows, thus I need to know what x was when the condition was true. I'm using python 3.5.0
The variable x refers to the scope of the generator passed to the any() function, so you can not print x outside of this generator.
any() just returns True or False.
Instead, you might use next():
print next(x for x in a if x in str)
And add a default value in the case no correct value is found:
s = next((x for x in a if x in str), None)
if s:
print s
Just a note: you should not create a variable which is called str because there is a built-in with the same name. This is considred as bad practice to overwrite it because this can lead to confusion.
Use any when you don't care which condition is true, as long as one of them is. Instead, use a for loop (with an optional else clause if no x was in str).
for x in a:
if x in str:
print x
break
else:
print "Nothing in 'a' found in 'str'"
Another solution:
print [x for x in a if x in str]
Useful in more complicated examples. e.g.
for
a = ['a', 'b', 'c']
str = 'a123c567b'
output will be
['a', 'b', 'c']
for
a = ['a', 'b', 'c']
str = 'a1c5c'
output will be:
['a', 'c']
a = ['a', 'b', 'c']
string = "a123"
for i in a:
if i in string:
print(i)

Python list append multiple elements

I want to append multiple elements to my list at once. I tried this
>>> l = []
>>> l.append('a')
>>> l
['a']
>>> l.append('b').append('c')
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
l.append('b').append('c')
AttributeError: 'NoneType' object has no attribute 'append'
>>>
how can I append 'b' and 'c' at once?
The method append() works in place. In other words, it modifies the list, and doesn't return a new one.
So, if l.append('b') doesn't return anything (in fact it returns None), you can't do:
l.append('b').append('c')
because it will be equivalent to
None.append('c')
Answering the question: how can I append 'b' and 'c' at once?
You can use extend() in the following way:
l.extend(('b', 'c'))
Use list.extend:
>>> l = []
>>> l.extend(('a', 'b'))
>>> l
['a', 'b']
Note that similar to list.append, list.extend also modifies the list in-place and returns None, so it is not possible to chain these method calls.
But when it comes to string, their methods return a new string. So, we can chain methods call on them:
>>> s = 'foobar'
>>> s.replace('o', '^').replace('a', '*').upper()
'F^^B*R'
l = []
l.extend([1,2,3,4,5])
There is a method for your purpose.

Python: list.sort() query when list contains different element types

Greetings Pythonic world. Day 4 of learning Python 3.3 and I've come across a strange property of list.sort.
I created a list of five elements: four strings, with a number in the middle. Trying to get list.sort to work gave the expected error because of mixing types:
>>> list = ['b', 'a', 3, 'd', 'c']
>>> list.sort()
Traceback (innermost last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>> list
['b', 'a', 3, 'd', 'c']
The list is unchanged.
But then I moved the number to the end, used list.sort again, and got this:
>>> list = ['b', 'a', 'd', 'c', 3]
>>> list.sort()
Traceback (innermost last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>> list
['a', 'b', 'c', 'd', 3]
OK, an error. But the list has sorted itself, kicking the number to the end. I couldn't find any explanation for this on this site or in Langtangen. Is there some underlying reason for this behaviour? Would it be useful in some situation?
From the Python 3 docs:
This method sorts the list in place, using only < comparisons between
items. Exceptions are not suppressed - if any comparison operations
fail, the entire sort operation will fail (and the list will likely be
left in a partially modified state).
The docs don't guarantee any behavior in particular, but the elements will more than likely be left part-way sorted. Whatever order they were in when the exception occurred, and this order can vary between implementations, or possibly (but unlikely) two subsequent runs of the program.
If you want to try to sort the items without worrying about an unfortunate re-ordering, you can use the sorted builtin function, which will return a new list rather than modify the original.
>>> seq = ['b', 'a', 3, 'd', 'c']
>>> try:
... seq = sorted(seq) # if sorted fails, result won't be assigned
... except Exception: # you may only want TypeError
... pass
...
>>> seq
['b', 'a', 3, 'd', 'c'] # list unmodified
EDIT:
to address everyone saying something like
once it sees two different types it raises an exception
I know you are probably aware that this kind of statement is an oversimplification, but I think without being clear, it's going to cause confusion. As an obvious example, you could sort a list with a mix of int and float.
The following example consists of two classes A and B which support comparison with each other through their respective __lt__ methods. It shows a list mixed of these two types sorted with list.sort() and then printed in sorted order with no exceptions raised:
class A:
def __init__(self, value):
self.a = value
def __lt__(self, other):
if isinstance(other, B):
return self.a < other.b
else:
return self.a < other.a
def __repr__(self):
return repr(self.a)
class B:
def __init__(self, value):
self.b = value
def __lt__(self, other):
if isinstance(other, A):
return self.b < other.a
else:
return self.b < other.b
def __repr__(self):
return repr(self.b)
seq = [A(10), B(2), A(8), B(16), B(9)]
seq.sort()
print(seq)
The output of this is:
[2, 8, 9, 10, 16]
it's not vital that you understand every detail of this. It's just to illustrate that a list of mixed types can work with list.sort() if all the pieces are there
I am writing below answer by assuming that I know the data types in the list, might not be efficient. My idea is to partition the given list into sublists based on data type, after that sort each individual list and combine.
input= ['b', 'a', 3, 'd', 'c']
strs = list(filter(lambda x : type(x) ==str,input))
ints = list(filter(lambda x: type(x) == int, input))
output = sorted(strs) + sorted(ints)
This nothing uncommon. Simply sort() do not check whether list contains consistent datatypes, instead it tries to sort. So once your element is at the end, it gets analyzed lately, and so algorithm did sorted part of the list before it found an error.
And no - it is not useful, as it heavily depends on the implemented sort mechanism.
depends on how the data needs to be sorted, but something like this can work
l = ['a',3,4,'b']
sorted([str(x) for x in l])
['3', '4', 'a', 'b']
I came up with the same problem recently, and didn't wanted to cast everything to a string, so I did this, hope it helps :)
list = ["a", 1, False, None, "b", (1,3), (1, 'a'),(1, [None, False]), True, 3, False]
type_weights = {}
for element in list:
if type(element) not in type_weights:
type_weights[type(element)] = len(type_weights)
print(sorted(list, key=lambda element: (type_weights[type(element)], str(element))))
It should return something like this:
['a', 'b', 1, 3, False, False, True, None, (1, 'a'), (1, 3), (1, [None, False])]
It should work with any data type (including custom classes)

Appending turns my list to NoneType [duplicate]

This question already has answers here:
Why do these list methods (append, sort, extend, remove, clear, reverse) return None rather than the resulting list?
(6 answers)
Closed 6 months ago.
In Python Shell, I entered:
aList = ['a', 'b', 'c', 'd']
for i in aList:
print(i)
and got
a
b
c
d
but when I tried:
aList = ['a', 'b', 'c', 'd']
aList = aList.append('e')
for i in aList:
print(i)
and got
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
for i in aList:
TypeError: 'NoneType' object is not iterable
Does anyone know what's going on? How can I fix/get around it?
list.append is a method that modifies the existing list. It doesn't return a new list -- it returns None, like most methods that modify the list. Simply do aList.append('e') and your list will get the element appended.
Delete your second line aList = aList.append('e') and use only aList.append("e"), this should get rid of that problem.
Generally, what you want is the accepted answer. But if you want the behavior of overriding the value and creating a new list (which is reasonable in some cases^), what you could do instead is use the "splat operator", also known as list unpacking:
aList = [*aList, 'e']
#: ['a', 'b', 'c', 'd', 'e']
Or, if you need to support python 2, use the + operator:
aList = aList + ['e']
#: ['a', 'b', 'c', 'd', 'e']
^ There are many cases where you want to avoid the side effects of mutating with .append(). For one, imagine you want to append something to a list you've taken as a function argument. Whoever is using the function probably doesn't expect that the list they provided is going to be changed. Using something like this keeps your function "pure" without "side effects".
Sometimes this error appears when you forgot to return a function at the end of another function and passed an empty list, interpreted as NoneType.
from this:
def func1():
...
func2(empty_list)
def func2(list):
...
# use list here but it interpreted as NoneType
to this:
def func1():
...
return func2(empty_list)
def func2(list):
...
# use list here, it will be interpreted as an empty List

Categories