Get string of certain length out of a list - python

What I am after is like this:
list1 = ["well", "455", "antifederalist", "mooooooo"]
Something that pulls "455" from the list because of the number of characters.

You can use next() with a generator:
>>> list1 = ["well", "455", "antifederalist", "mooooooo"]
>>>
>>> next(s for s in list1 if len(s) == 3)
'455'
next() also lets you specify a "default" value to be returned if the list doesn't contain any string of length 3. For instance, to return None in such a case:
>>> list1 = ["well", "antifederalist", "mooooooo"]
>>>
>>> print next((s for s in list1 if len(s) == 3), None)
None
(I used an explicit print because Nones don't print by default in interactive mode.)
If you want all strings of length 3, you can easily turn the approach above into a list comprehension:
>>> [s for s in list1 if len(s) == 3]
['455']

filter(lambda s: len(s) == 3, list1)

And if you're looking to pull all items out of the list greater than some length:
list2 = [string for string in list1 if len(string) >= num_chars]

Related

if-else in python list comprehensions [duplicate]

This question already has answers here:
How can I partition (split up, divide) a list based on a condition?
(41 answers)
Closed 6 years ago.
is it possible to write list comprehensions for the following python code:
for str in range(0,len(mixed_content)):
if (mixed_content[str].isdigit()):
num_list.append(mixed_content[str])
else:
string_list.append(mixed_content[str])
can we use else block in list comprehensions ? I tried to write list comprehensions for above code :
num_list , string_list = [ mixed_content[str] for str in range(0,len(mixed_content)) if(mixed_content[str].isdigit()) else ]
It's not possible as-is, but if you're looking for one-liners you can do that with a ternary expression inside your loop (saves a test and is compact):
num_list=[]
string_list=[]
for s in ["45","hello","56","foo"]:
(num_list if s.isdigit() else string_list).append(s)
print(num_list,string_list)
result:
['45', '56'] ['hello', 'foo']
Notes:
despite the parenthesized syntax and the context of the question, (num_list if s.isdigit() else string_list) is not a generator, a ternary expression (protected between parentheses to counter .append precedence) which returns num_list if s is a sequence of (positive) digits and string_list if s otherwise.
this code won't work with negative numbers because isdigits will return false. You'll have to code a special function for that (classical problem here on SO)
You can only construct one list at a time with list comprehension. You'll want something like:
nums = [foo for foo in mixed_list if foo.isdigit()]
strings = [foo for foo in mixed_list if not foo.isdigit()]
Here is an example of using x if b else y in a list comprehension.
mixed_content = "y16m10"
num_list, string_list = zip(
*[(ch, None) if ch.isdigit() else (None, ch) for ch in mixed_content])
num_list = filter(None, num_list)
string_list = filter(None, string_list)
print num_list, string_list
Let's initialize variables:
>>> mixed_content='ab42c1'; num_list=[]; string_list=[]
Because the OP asked about using "if-else in python list comprehensions," let's show that that can be done:
>>> [num_list.append(c) if c.isdigit() else string_list.append(c) for c in mixed_content]
[None, None, None, None, None, None]
Let's verify that we have the lists that you want:
>>> num_list, string_list
(['4', '2', '1'], ['a', 'b', 'c'])
You can accomplish what you want with two list comprehensions:
num_list = [num for num in mixed_content if num.isdigit()]
string_list = [string for string in mixed_content if not string.isdigit()]
The else clause is not supported in list comprehensions:
>>> [c for c in range(5) if c == 1 else 0]
SyntaxError: invalid syntax
A super messy and unpractical way of doing is:
mixed_content = ['a','b','c',"4"]
string_list = []
print [y for y in [x if mixed_content[x].isdigit() else string_list.append(mixed_content[x]) for x in range(0,len(mixed_content))] if y != None]
print string_list
Returns:
[3]
['a', 'b', 'c']
Basically list comprehension for your condition and then filter that list comprehension to only accept non None

Use list comprehension to print out a list with words of length 4

I am trying to write a list comprehension that uses List1 to create a list of words of length 4.
List1 = ['jacob','batman','mozarella']
wordList = [words for i in range(1)]
print(wordList)
This prints out the wordList however with words of length higher than 4
I am looking for this program to print out instead:
['jaco','batm','moza']
which are the same words in List1 but with length 4
I tried this and it didn't work
wordList = [[len(4)] words for i in range(1)]
any thoughts ?
You could use this list comp
>>> List1 = ['jacob','batman','mozarella']
>>> [i[:4] for i in List1]
['jaco', 'batm', 'moza']
Ref:
i[:4] is a slice of the string of first 4 characters
Other ways to do it (All have their own disadvantages)
[re.sub(r'(?<=^.{4}).*', '', i) for i in List1]
[re.match(r'.{4}', i).group() for i in List1]
[''.join(i[j] for j in range(4)) for i in List1]
[i.replace(i[4:],'') for i in List1] ----- Fails in case of moinmoin or bongbong
Credit - Avinash Raj
len() function return the length of string in your case. So list compression with len function will give the list of all item lenght.
e.g.
>>> List1 = ['jacob','batman','mozarella']
>>> [len(i) for i in List1]
[5, 6, 9]
>>>
Use slice() list method to get substring from the string. more info
e.g.
>>> a = "abcdef"
>>> a[:4]
'abcd'
>>> [i[:4] for i in List1]
['jaco', 'batm', 'moza']
Python beginner
Define List1.
Define empty List2
Use for loop to iterate every item from the List1
Use list append() method to add item into list with slice() method.
Use print to see result.
sample code:
>>> List1 = ['jacob','batman','mozarella']
>>> List2 = []
>>> for i in List1:
... List2.append(i[:4])
...
>>> print List2
['jaco', 'batm', 'moza']
>>>
One more way, now using map function:
List1 = ['jacob','batman','mozarella']
List2 = map(lambda x: x[:4], List1)

Efficiently test if two lists have the same elements and length

I got 2 lists:
alist = ['A','B','C','D']
anotherList = ['A','C','B','D']
would like to write a function which returns True if both lists contain the exact same elements, and are same length. I'm kinda new on this stuff, so I got this, which I'm pretty sure it's terrible, and I'm trying to find a more efficient way. Thanks!
def smyFunction(aList,anotherList):
n = 0
for element in aList:
if element in anotherList:
n = n+1
if n == len(aList):
return True
else:
return False
The two ways that come to mind are:
1) Use collections.Counter
>>> from collections import Counter
>>> Counter(alist) == Counter(anotherList)
True
2) Compare the sorted lists
>>> sorted(alist) == sorted(anotherList)
True
Sort the lists with sorted and then compare them with ==:
>>> alist = ['A','B','C','D']
>>> anotherList = ['A','C','B','D']
>>> def smyFunction(aList,anotherList):
... return sorted(aList) == sorted(anotherList)
...
>>> smyFunction(alist, anotherList)
True
>>>
You need to sort them first in case the elements are out of order:
>>> alist = ['A','B','C','D']
>>> anotherList = ['D','A','C','B']
>>> alist == anotherList
False
>>> sorted(alist) == sorted(anotherList)
True
>>>
Actually, it would probably be better to test the length of the lists first and then use sorted:
return len(alist) == len(anotherList) and sorted(alist) == sorted(anotherList)
That way, we can avoid the sorting operations if the lengths of the list are different to begin with (using len on a list has O(1) (constant) complexity, so it is very cheap).
If there aren't duplicates, use a set, it doesn't have an order:
set(alist) == set(anotherList)
try like this:
def check(a,b):
return sorted(a) == sorted(b)

Cross-matching two lists

I have two lists where I am trying to see if there is any matches between substrings in elements in both lists.
["Po2311tato","Pin2231eap","Orange2231edg","add22131dfes"]
["2311","233412","2231"]
If any substrings in an element matches the second list such as "Po2311tato" will match with "2311". Then I would want to put "Po2311tato" in a new list in which all elements of the first that match would be placed in the new list. So the new list would be ["Po2311tato","Pin2231eap","Orange2231edg"]
You can use the syntax 'substring' in string to do this:
a = ["Po2311tato","Pin2231eap","Orange2231edg","add22131dfes"]
b = ["2311","233412","2231"]
def has_substring(word):
for substring in b:
if substring in word:
return True
return False
print filter(has_substring, a)
Hope this helps!
This can be a little more concise than the jobby's answer by using a list comprehension:
>>> list1 = ["Po2311tato","Pin2231eap","Orange2231edg","add22131dfes"]
>>> list2 = ["2311","233412","2231"]
>>> list3 = [string for string in list1 if any(substring in string for substring in list2)]
>>> list3
['Po2311tato', 'Pin2231eap', 'Orange2231edg']
Whether or not this is clearer / more elegant than jobby's version is a matter of taste!
import re
list1 = ["Po2311tato","Pin2231eap","Orange2231edg","add22131dfes"]
list2 = ["2311","233412","2231"]
matchlist = []
for str1 in list1:
for str2 in list2:
if (re.search(str2, str1)):
matchlist.append(str1)
break
print matchlist

Python methods to find duplicates

Is there a way to find if a list contains duplicates. For example:
list1 = [1,2,3,4,5]
list2 = [1,1,2,3,4,5]
list1.*method* = False # no duplicates
list2.*method* = True # contains duplicates
If you convert the list to a set temporarily, that will eliminate the duplicates in the set. You can then compare the lengths of the list and set.
In code, it would look like this:
list1 = [...]
tmpSet = set(list1)
haveDuplicates = len(list1) != len(tmpSet)
Convert the list to a set to remove duplicates. Compare the lengths of the original list and the set to see if any duplicates existed.
>>> list1 = [1,2,3,4,5]
>>> list2 = [1,1,2,3,4,5]
>>> len(list1) == len(set(list1))
True # no duplicates
>>> len(list2) == len(set(list2))
False # duplicates
Check if the length of the original list is larger than the length of the unique "set" of elements in the list. If so, there must have been duplicates
list1 = [1,2,3,4,5]
list2 = [1,1,2,3,4,5]
if len(list1) != len(set(list1)):
#duplicates
The set() approach only works for hashable objects, so for completness, you could do it with just plain iteration:
import itertools
def has_duplicates(iterable):
"""
>>> has_duplicates([1,2,3])
False
>>> has_duplicates([1, 2, 1])
True
>>> has_duplicates([[1,1], [3,2], [4,3]])
False
>>> has_duplicates([[1,1], [3,2], [4,3], [4,3]])
True
"""
return any(x == y for x, y in itertools.combinations(iterable, 2))

Categories