Ordered subset in python [duplicate] - python

This question already has answers here:
How to test if one string is a subsequence of another?
(4 answers)
Python list filtering: remove subsets from list of lists
(10 answers)
Closed 4 years ago.
I know many similar questions has been asked before with answers but my concern is related to builtin functionality rather than my own logic of loops and indexes etc.
In my python app, I need to check if listA is subset of listB. I've done this with the help of sets like this
set(listA) < set(listB)
It works fine overall but I also need to check order of objects in list. e.g.
x = ['a','b','c','d']
xx = ['a', 'c']
xxx = ['c' , 'a']
so according to sets definition;
set(xx) < set(x) returns true and set(xxx) < set(x) also returns true...
But I need something that returns false for 2nd case.
Is there any builtin functionality in python or I need to implement my own logic to get required result?

I think a better word for this operation is a subsequence.
You need to write this yourself, but you can do it fairly easily by walking both lists together:
def is_subsequence(a, b):
b_it = iter(b)
try:
for a_val in a:
while next(b_it) != a_val:
pass
except StopIteration:
return False
else:
return True
used as:
>>> is_subsequence(xx, x)
True
>>> is_subsequence(xxx, x)
False
Edit: Searching for "subsequence" finds this great answer.

Related

Filter method in Python is not working as expected for strings [duplicate]

This question already has an answer here:
python is operator behaviour with string [duplicate]
(1 answer)
Closed 4 months ago.
I am filtering a list of strings according to the following condition.
list_of_strings = ["foo-bar", "foo", "bar"]
print(list(filter(lambda x: x is not "foo-bar", list_of_strings)))
>>> ["foo-bar", "foo", "bar"] # This is output. But I expected "foo-bar" to be removed
But this is working fine with !=
How is this happening?
The problem is in the filtering condition. Should be:
lambda x: x != "foo-bar"
To compare two strings use != and == (equality test).
is is a test for an identical object.
>>> "A" is "A"
True
This is an efect of an optimisation called interning. If a constant is used several times, the Python interpreter tries to save only one copy of it. You cannot rely on that.
>>> "a".upper() is "A"
False
>>> "a".upper() == "A"
True

List comprehension syntax - how to use ... if... else? [duplicate]

This question already has answers here:
if/else in a list comprehension
(12 answers)
Is it possible to use 'else' in a list comprehension? [duplicate]
(6 answers)
Closed 3 years ago.
I'm just getting started with Python and was reading about list comprehensions.
The following code:
my_list = [x ** x for x in range(1,11) if x % 2 == 0]
print(my_list)
... produces this output:
[4, 256, 46656, 16777216, 10000000000]
I then tried this code:
my_list = [x ** x for x in range(1,11) if x % 2 == 0 else 7]
print(my_list)
... but I got a syntax error starting at the second "e" in else.
Can someone explain why I'm getting a syntax error? I'd like to have the list create a list of even squares based on the value of the base (x), and to have the value "49" if the list value is not an "even number" square.
In this case, you would want
my_list = [x ** x if x % 2 == 0 else 49 for x in range(1,11)]
If you use an if at the end of a list comprehension like that, it is used to select which elements to include. If you want a different result depending on the case, you need to use a ternary if at the beginning instead.
For more info, take a look at the docs here. To quote:
A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it.
There is no support for else here, presumably because a ternary if (if condition then foo else bar) in the 'body' of the comprehension already accomplishes this and "There should be one-- and preferably only one --obvious way to do it."

What does < or > mean in python while comparing strings [duplicate]

This question already has answers here:
How are strings compared?
(7 answers)
Closed 6 years ago.
I have written this code in python 3.5
x="absx"
o="abcdef"
and if i am doing this operation,
x<o
False #it return's False and i think it should return True
So what is '<' doing in case of strings and why is it not returning true.
how is it comparing x and o?
The < or > would result in lexicographic comparison of the two strings:
>>> x="absx"
>>> o="abcdef"
>>> x > o
True
Lexicographic ordering is same as dictionary ordering, and basically, the operators are checking for which string would come earlier (or later) in a dictionary order. The behavior is same for both Python 2 and 3.
The final result does not depend on the size of the string, Example:
>>> "a" < "aaaaa"
True
In example above "a" would come before "aaaaa" when written in dictionary order. To compare by length of strings, use the len() function on the strings.
Lexicographic comparison. In your case o would come after x.

what is difference between [None] and [] in python? [duplicate]

This question already has answers here:
What is a None value?
(9 answers)
Is there a difference between "==" and "is"?
(13 answers)
Closed 6 years ago.
I think [None] is same as [], but in my test , maybe there is something...
>>>print len([])
0
>>>print len([None])
1
when should i use the None ? and []
and another interesting question
>>>c= []
>>>d= []
>>>print c is d
False
>>>a= 1
>>>b=1
print a is b
True
why empty list's id granting that is different?
[] is an empty list
[None] is a list with one element. That one element is None
is checks for reference equality. If both objects refer to the same object by reference then is will return true.
a = []
b = a
a is [] #false
a is b #true
[None] does not mean that there is nothing in the list. None is a keyword in python which has a special meaning. It is like NIL or NULL in other languages.
When you say [None], you are saying "I would like to have a list which contains the special object called None". This is different than saying "I would like a list which contains no elements" (by typing []).
Question 1:
None is an object. It is of type "NoneType".
This can be seen by doing something like this in the terminal:
>>> type(None)
<type 'NoneType'>
So, when you put this object in a list, the list has one element.
Question 2:
The assignment operator in Python, =, is used to attach a name to an object. In the case of immutable objects, like integers, multiple names can be attached to the same object. That is what you are doing with a and b. So, when you test their identity, using the is operator, you see that the two names point to the identical object.
Alternatively, when you attach a name to a newly created list (which you created with the [] operator) it is a different list each time.
None is a valid element, but you can treat it like a stub or placeholder. So it counts as an element inside the list even if there is only a None.
For (equality) comparisons you shouldn't use is. Use ==!
Because is can lead to strange behaviour if you don't know exactly when and how to use it. For example:
>>> 1900 is 1900
True
>>> a = 1900
>>> b = 1900
>>> a is b
False
>>> a, b = 1900, 1900
>>> a is b
True
This rather strange behaviour is explained for example in this question: Why does Python handle '1 is 1**2' differently from '1000 is 10**3'?
This won't happen when you use ==:
>>> a == b
True
>>> 1900 == 1900
True
like one would expect.
You want to use None to imply that there is no valid object. You want to use [] to imply an object that is of type list and has no elements.
[None] is a list with one element which is None
>>>c= [] # This is a new list object
>>>d= [] # This is another new list object
In Python , x is y is used to check whether x and y are the same objects.
Here, c and d point to different list objects.
so,
>>>print c is d
False
is expected.
On the other hand,
>>>c= [] # This is a new list object
>>>d = c # This is the same object as c
>>>print c is d
True
Here, a and b are primitives, not objects
>>>a= 1
>>>b=1
So, this is expected:
print a is b
True

Checking if two lists share at least one element [duplicate]

This question already has answers here:
Test if lists share any items in python
(9 answers)
Closed 4 years ago.
I have two lists, for example:
a = ["mail1", "mail2", "mail3", "mail4"]
b = ["mail2", "mail5"]
and I want to check if any of the elements in list b also appears in list a.
I wanted to know if there is a way (and what is it) to do this without a for loop.
Also I wanted to know how can I create a list of boolean values, where each value will be the result of the comparison of values a[i] and b[i], something like:
[z for i, j in zip(a, b) z = i == j] # (just with the right syntax)
z will be 1 if in some place i == j, so I can check the array for any 'True' values.
You can use any:
any(x in a for x in b)
The nice thing about this generator expression is that any will return True as soon as the generator yields a True, i.e. there won't be redundant x in a lookups.
Edit:
You can improve the time complexity by making a set from a.
a_set = set(a)
any(x in a_set for x in b)
Regarding your new question:
[x == y for x,y in zip(a,b)]
Elegant way is to use sets:
a = ["mail1", "mail2", "mail3", "mail4"]
b = ["mail2", "mail5"]
anb = set(a) & set(b)
print anb
if anb:
print True
>>> set(['mail2'])
>>> True
The any function takes in an iterable (See documentation here), so the answer should be any([x in a for x in b])

Categories

Resources