String vs list membership check - python

So i'm wondering why this:
'alpha' in 'alphanumeric'
is True, but
list('alpha') in list('alphanumeric')
is False.
Why does x in s succeed when x is a substring of s, but x in l doesn't when x is a sublist of l?

When you use list function with any iterable, a new list object will be created with all the elements from the iterable as individual elements in the list.
In your case, strings are valid Python iterables, so
>>> list('alpha')
['a', 'l', 'p', 'h', 'a']
>>> list('alphanumeric')
['a', 'l', 'p', 'h', 'a', 'n', 'u', 'm', 'e', 'r', 'i', 'c']
So, you are effectively checking if one list is a sublist of another list.
In Python only Strings have the in operator to check if one string is part of another string. For all other collections, you can only use individual members. Quoting the documentation,
The operators in and not in test for collection membership. x in s evaluates to true if x is a member of the collection s, and false otherwise. x not in s returns the negation of x in s. The collection membership test has traditionally been bound to sequences; an object is a member of a collection if the collection is a sequence and contains an element equal to that object. However, it make sense for many other object types to support membership tests without being a sequence. In particular, dictionaries (for keys) and sets support membership testing.
For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.
For the Unicode and string types, x in y is true if and only if x is a substring of y. An equivalent test is y.find(x) != -1. Note, x and y need not be the same type; consequently, u'ab' in 'abc' will return True. Empty strings are always considered to be a substring of any other string, so "" in "abc" will return True.

For the second one you are asking if
['a', 'l', 'p', 'h', 'a'] in ['a', 'l', 'p', 'h', 'a', 'n', 'u', 'm', 'e', 'r', 'i', 'c']
and there is no sub-list in the second list only characters.
['a', 'l', 'p', 'h', 'a'] in [['a', 'l', 'p', 'h', 'a'], ['b', 'e', 't', 'a']]
would be true

lists determine membership if an item is equal to one of the list members.
strs determine whether string a is in string b if a substring of b is equal to a.

I suppose you are looking for the fact that string and list has different implementations of __contains__ magic method.
https://docs.python.org/2/reference/datamodel.html#object.contains
This is why 'alpha' in 'alphanumeric' is True, but
list('alpha') in list('alphanumeric') is False

maybe you should try issubset method.
>>> set('alpha').issubset(set('alphanumeric'))
True
although set('alpha') returns set(['a', 'p', 'l', 'h']), and set('alphanumeric'), set(['a', 'c', 'e', 'i', 'h', 'm', 'l', 'n', 'p', 'r', 'u']).
set method makes a list ignoring repetetive elements.

Related

How can I reference a string (e.g. 'A') to the index of a larger list (e.g. ['A', 'B', 'C', 'D', ...])?

I have been racking my brain and scouring the internet for some hours now, please help.
Effectively I am trying to create a self-contained function (in python) for producing a caesar cipher. I have a list - 'cache' - of all letters A-Z.
def caesarcipher(text, s):
global rawmessage #imports a string input - the 'raw message' which is to be encrypted.
result = ''
cache = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Is it possible to analyze the string input (the 'rawmessage') and attribute each letter to its subsequent index position in the list 'cache'? e.g. if the input was 'AAA' then the console would recognise it as [0,0,0] in the list 'cache'. Or if the input was 'ABC' then the console would recognise it as [0,1,2] in the list 'cache'.
Thank you to anyone who makes the effort to help me out here.
Use a list comprehension:
positions = [cache.index(letter) for letter in rawmessage if letter in cache]
You can with a list comprehension. Also you can get the letter from string.
import string
print([string.ascii_uppercase.index(c) for c in "AAA"])
# [0, 0, 0]
print([string.ascii_uppercase.index(c) for c in "ABC"])
# [0, 1, 2]
result = []
for i in list(rawmessage):
result.append(cache.index(i))

Python rearrange list based on another list

I want to rearrange a list based on another list which have common elements between them.
my list = ['q','s','b','f','l','c','x','a']
base_list = ['z','a','b','c']
Above lists have common 'a','b' and 'c' as common elements.the expected outcome for is as below
my_result = ['a','b','c','q','s','f','l','x']
Thanks in Advance
Sky
my_list = ['q','s','b','f','l','c','x','a']
base_list = ['z','a','b','c']
res1=[x for x in base_list if x in my_list] # common elements
res2=[x for x in my_list if x not in res1] #
res3=res1+res2
Output :
['a', 'b', 'c', 'q', 's', 'f', 'l', 'x']
Create a custom key for sorted as shown in this document. Set the value arbitrarily high for the letters that don't appear in the base_list so they end up in the back. Since sorted is considered stable those that aren't in the base_list will remain untouched in terms of original order.
l = ['q','s','b','f','l','c','x','a']
base_list = ['z','a','b','c']
def custom_key(letter):
try:
return base_list.index(letter)
except ValueError:
return 1_000
sorted(l, key=custom_key)
['a', 'b', 'c', 'q', 's', 'f', 'l', 'x']
A (probably non optimal) way:
>>> sorted(my_list, key=lambda x: base_list.index(x) if x in base_list
else len(base_list)+1)
['a', 'b', 'c', 'q', 's', 'f', 'l', 'x']

How does Python's random.shuffle() alter the value of a list without returning anything and is this something any Python coder can do as well? [duplicate]

This question already has answers here:
Why can a function modify some arguments as perceived by the caller, but not others?
(13 answers)
Why does random.shuffle return None?
(5 answers)
Closed 2 years ago.
edit:
When I asked this I did not properly understand the concept of mutable and immutable objects, and the variables that point to them
I just noticed I wasn't getting a return from random.shuffle(). I realised this makes sense as you would logically want to work with the original list unless specified otherwise.
>>> import string
>>> import random
>>> letters = list(string.ascii_lowercase)
>>> print(letters)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
>>> rand_alpha = random.shuffle(letters)
>>> print(rand_alpha)
None
>>> print(letters)
['f', 'c', 'n', 'u', 'x', 'y', 'q', 'j', 's', 'v', 'w', 'o', 'p', 'z', 't', 'm', 'k', 'd', 'e', 'a', 'g', 'i', 'h', 'l', 'r', 'b']
This led me to wonder whether altering a list in another scope is something people do (and should be cautious not to do accidentally) or is this something special within the Python standard library?
I checked the code - and did a few searches - but I didn't find anything that made this clearer for me.
There are functions that work in-place and others that return their result. For the second type, you have to assign their return value to something to make use of it.
Probably the easiest\most common example is the .sort list method and the sorted function; the first works in place much like your shuffle while the second returns a sorted copy of the list passed.
Does this help ?
The shuffle fun functions shuffles the list and stores it inside that list only, it does not make a separate list. If you want a separate list, you can duplicate this list and then shuffle it like this
letters=["a","v"]
lettersCopy = letters
lettersCopy.shuffle()
You should always alter dat(lists) carefully because user entered data cannot be retrieved. It is done in other scopes when people want to save storage.

Python: Joining characters in sublists of list of lists

I have a huge list of lists, this is a section of it:
[['cusA', 'zupT', 'rcnA', 'cusA', 'zupT', 'zupT']]
I did the following operation on the entire list of lists:
[list(x) for x in set(tuple(x) for x in my_list)]
because I would like to have unique information in the sublists. This returned the following:
[['c', 'u', 's', 'A'], ['r', 'c', 'n', 'A'], ['z', 'u', 'p', 'T']]
Which is great, since it did become unique, but now I need them to be in their original from, without being broken up character-by-character.
Is there any way to re-join them inside the sublists?
Instead of list(x), use ''.join(x).
But you can just put the strings themselves in a set instead of calling tuple: list(set(my_list)).
If the ordering of the contents of the inner lists does not matter, you can turn them into a set, which is a an un-ordered collection of unique elements, and then turn that set back into a list:
result = [list(set(li)) for li in my_list]
Prints:
[['cusA', 'rcnA', 'zupT']]
as you already mentioned: you can join the strings:
print(''.join(['c', 'u', 's', 'A'])) # cusA
for your whole list you could do this:
lst = [['c', 'u', 's', 'A'], ['r', 'c', 'n', 'A'], ['z', 'u', 'p', 'T']]
str_lst = [''.join(item) for item in lst]
print(str_lst) # ['cusA', 'rcnA', 'zupT']
note that there is no point in creating a list of single characters; a string itself behaves exactly like a list of characters (an immutable one, though); so you could directoy do this:
print(set(['cusA', 'zupT', 'rcnA', 'cusA', 'zupT', 'zupT']))
# {'zupT', 'cusA', 'rcnA'}
# if you need a list again instead of a set:
print(list(set(['cusA', 'zupT', 'rcnA', 'cusA', 'zupT', 'zupT'])))
# ['zupT', 'cusA', 'rcnA']
that will not preserve the order though...

What i did wrong in my python function?

def make_str_from_row(board, row_index):
''' (list of list of str, int) -> str
Return the characters from the row of the board with index row_index
as a single string.
>>> make_str_from_row([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 0)
'ANTT'
'''
for i in range(len(board)):
i = row_index
print(board[i])
This prints ['A', 'N', 'T', 'T']
How do I print it like this 'ANTT' instead?
Well, you got what you told to print!
board is a list of list of strs, so board[i] must be a list of strs, and when you write print(board[i]), you get a list!
You may need to write this:
print(''.join(board[i]))
You could simplify that a whole lot by using
>>> def make_str_from_row(board, row_index):
... print repr(''.join(board[row_index]))
...
>>> make_str_from_row([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 0)
'ANTT'
The reason you get that output is because you print a list since the elements of board are lists. By using join, you get a string.
Also, I don't understand why you use a loop if are going to change the index you loop over.
I think this was what you were trying to do:
def make_str_from_row(board, row_index):
''' (list of list of str, int) -> str
Return the characters from the row of the board with index row_index
as a single string.
>>> make_str_from_row([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 0)
'ANTT'
'''
for cell in board[row_index]:
print cell,

Categories