Removing strings from a list dependent on their length? - python

I am trying to remove any strings from this list of strings if their length is greater than 5. I don't know why it is only removing what seems to be random strings. Please help. The item for sublist part of the code just changes the list of lists, into a normal list of strings.
list2 = [['name'],['number'],['continue'],['stop'],['signify'],['tester'],['racer'],['stopping']]
li = [item for sublist in list2 for item in sublist]
var=0
for words in li:
if len(li[var])>5:
li.pop()
var+=1
print(li)
The output is: ['name', 'number', 'continue', 'stop', 'signify']

Just include the check when flattening the list:
list2 = [['name'],['number'],['continue'],['stop'],['signify'],['tester'],['racer'],['stopping']]
li = [item for sublist in list2 for item in sublist if len(item) <= 5]
['name', 'stop', 'racer']

You can use a list comprehension to build a new list with only items that are 5 or less in length.
>>> l = ['123456', '123', '12345', '1', '1234567', '12', '1234567']
>>> l = [x for x in l if len(x) <= 5]
>>> l
['123', '12345', '1', '12']

list(filter(lambda x: len(x[0]) <= 5, list2))

Related

Find List2 in List1 at starting Position

List1 = ['RELEASE', 'KM123', 'MOTOR', 'XS4501', 'NAME']
List2 = ['KM', 'XS', 'M']
Now I am using code that only searches List2 in List1 in any position.
Result = [ s for s in List1 if any(xs in s for xs in List2]
Output :
[KM123', 'MOTOR', 'XS4501', 'NAME']
But I don't want 'NAME' to be in the list because it contains 'M' not in the starting. Any help...
Use str.startswith() which checks if a string starts with a particular sequence of characters:
[s for s in List1 if any(s.startswith(xs) for xs in List2)]
Looks like you can use str.startswith
Ex:
List1 = ['RELEASE', 'KM123', 'MOTOR', 'XS4501', 'NAME']
List2 = ('KM', 'XS', 'M') #convert to tuple
result = [ s for s in List1 if s.startswith(List2)]
print(result) #-->['KM123', 'MOTOR', 'XS4501']

Substring filter list elements by another list in Python

I have two lists looking like:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
I want to substring filter list1 by elements of list2 and get expected output as follows:
outcome = ['bj-100-cy', 'sh-200-pd']
When doing:
list1 = str(list1)
list2 = str(list2)
outcome = [x for x in list2 if [y for y in list1 if x in y]]
I get a result like this: ['[', '1', '0', '0', ',', ' ', '2', '0', '0', ']'].
How can I filter it correctly? Thanks.
Reference related:
Is it possible to filter list of substrings by another list of strings in Python?
List comprehension and any:
[i for i in list1 if any(i for j in list2 if str(j) in i)]
any to check if any element of list2 is a substring of the list1 item (__contains__) being iterated over.
Example:
In [92]: list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
...: list2 = [100, 200]
...:
In [93]: [i for i in list1 if any(i for j in list2 if str(j) in i)]
Out[93]: ['bj-100-cy', 'sh-200-pd']
You can use any:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
list2 = [str(x) for x in list2]
outcome = [s for s in list1 if any(x in s for x in list2)]
any returns True if any of the conditions you give it are True.
list1 = str(list1)
list2 = str(list2)
You are converting your list into a string with the above statements. So when you iterate in a for loop, you are iterating each characters, instead of each word.
So you should remove string conversion and instead do a list comprehension as follows.
Also, in your outcome file instead of checking if the word in list2 is in list1, you are checking the opposite. So you got like 100 and 200 as chars which are in list 2.
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
outcome = [x for x in list1 for y in list2 if str(y) in x]
You can try this one:
list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
list2 = [100, 200]
outcome = []
for item in list1:
if any(str(i) in item for i in list2):
outcome.append(item)
output:
['bj-100-cy', 'sh-200-pd']
Another alternative list comprehension :
>>> list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
>>> list2 = [100, 200]
>>> occur = [i for i in list1 for j in list2 if str(j) in i]
>>> occur
['bj-100-cy', 'sh-200-pd']
You can use builtin filter method to filter the list based on your condition. Your condition requires python in operator to search for needle([100, 200]) in haystack ([['bj-100-cy','bj-101-hd',...]]).
We can use contains method to simplify search syntax.
Code
from operator import contains
filter(lambda x: any(contains(x,str(y)) for y in list2), list1)
Example
>>> list1 = ['bj-100-cy','bj-101-hd','sh-200-pd','sh-201-hp']
>>> list2 = [100, 200]
>>> for item in filter(lambda x: any(contains(x,str(y)) for y in list2), list1):
... print(item)
...
bj-100-cy
sh-200-pd
You can use regex:
import re
list1 = ['bj-100-cy', 'bj-101-hd', 'sh-200-pd', 'sh-201-hp']
list2 = [100, 200]
pattern = re.compile('|'.join(map(str, list2)))
list(filter(pattern.search, list1))
# ['bj-100-cy', 'sh-200-pd']

Flatten lists of variable depths in Python

I have a list of n lists. Each internal list contains a combination of (a) strings, (b) the empty list, or (c) a list containing one string. I would like to transform the inside lists so they only contain the strings.
I have a list like this for example:
[[[],["a"],"a"],[["ab"],[],"abc"]]
and I would like it to be like this:
[["","a","a"],["ab","","abc"]]
I know I could probably go through with a loop but I am looking for a more elegant solution, preferably with a list comprehension.
List comprehension:
>>> original = [[[],["a"],"a"],[["ab"],[],"abc"]]
>>> result = [['' if not item else ''.join(item) for item in sublist] for sublist in original]
>>> result
[['', 'a', 'a'], ['ab', '', 'abc']]
As every element of the list that you'd like to flatten is iterable, instead of checking of being instance of some class (list, string) you can actually make use of duck-typing:
>> my_list = [[[],["a"],"a"],[["ab"],[],"abc"]]
>> [list(map(lambda x: ''.join(x), elem)) for elem in my_list]
Or more readable version:
result = []
for elem in my_list:
flatten = map(lambda x: ''.join(x), elem)
result.append(list(flatten))
Result:
[['', 'a', 'a'], ['ab', '', 'abc']]
It's quite pythonic to not to check what something is but rather leverage transformation mechanics to adaptive abilities of each of the structure.
Via list comprehension:
lst = [[[],["a"],"a"],[["ab"],[],"abc"]]
result = [ ['' if not v else (v[0] if isinstance(v, list) else v) for v in sub_l]
for sub_l in lst ]
print(result)
The output:
[['', 'a', 'a'], ['ab', '', 'abc']]
original_list = [[[],["a"],"a"],[["ab"],[],"abc"]]
flatten = lambda x: "" if x == [] else x[0] if isinstance(x, list) else x
flattened_list = [[flatten(i) for i in j] for j in original_list]

Python - removing items in multidimensional array

I have a multidimensional array such as this:
[["asdf","bmnl", "123","456,"0","999","1234","3456"],["qwer","tyui","789","657,"122","9","673","1"]]
However, in the multidimensional array, only the last 6items of each array are needed and the first two are not needed. How can I remove the first two pieces of data from each of the arrays within the multidimensional array so it would look like:
[["123","456,"0","999","1234","3456"],["789","657,"122","9","673","1"]]
So far, I have done this:
list1 = []
list2 = []
for row in rows:
list1.append(row[0].split(',')) #to put the split list into the top i i.e. [["asdf","bmnl", "123","456,"0","999","1234","3456"]["qwer","tyui","789","657,"122","9","673","1"]]
for i in list1:
for index in len(list1):
if index >=2:
list2.append(index) #this does not work and causes errors
How could I go about fixing this so the output would be:
[["123","456,"0","999","1234","3456"],["789","657,"122","9","673","1"]]
Thanks
Just use a list comprehension and grab every element from index 2 and beyond in each sublist:
>>> array = [["asdf","bmnl", "123","456","0","999","1234","3456"],["qwer","tyui","789","657","122","9","673","1"]]
>>> [sublist[2:] for sublist in array]
[['123', '456', '0', '999', '1234', '3456'], ['789', '657', '122', '9', '673', '1']]
lst = [["asdf","bmnl", "123","456","0","999","1234","3456"],["qwer","tyui","789","657","122","9","673","1"]]
for i in lst:
del i[0:2] #deleting 0 and 1 index from each list
print lst
This is a typical use case for a list comprehension:
list2 = [item[2:] for item in list1]
You can use a list comprehension like below:
[item[2:] for item in my_list]
item[2:] called list slicing, and it means that for each sub-list of my_list, we take items from the index 2 till the last item.
Output:
>>> my_list = [["asdf", "bmnl", "123", "456", "0", "999", "1234", "3456"], ["qwer", "tyui", "789", "657", "122", "9", "673", "1"]]
>>>
>>> [item[2:] for item in my_list]
[['123', '456', '0', '999', '1234', '3456'], ['789', '657', '122', '9', '673', '1']]
start = [["asdf","bmnl", "123","456","0","999","1234","3456"],
["qwer","tyui","789","657","122","9","673","1"]]
list_1, list_2 = [i[2:] for i in start] # I use list comprehension to create a multidimensional
# list that contains slices of each object in the base
# list and unwrap it to list_1 and list_2
Same as
n_list = [] #create an empty new list
for i in start: #loop through the origional
n_list.append(i[2:]) #append slices of each item to the new list
list_1, list_2 = n_list #unwrap the list

How to convert list of intable strings to int

In Python, I want to convert a list of strings:
l = ['sam','1','dad','21']
and convert the integers to integer types like this:
t = ['sam',1,'dad',21]
I tried:
t = [map(int, x) for x in l]
but is showing an error.
How could I convert all intable strings in a list to int, leaving other elements as strings?
My list might be multi-dimensional. A method which works for a generic list would be preferable:
l=[['aa','2'],['bb','3']]
I'd use a custom function:
def try_int(x):
try:
return int(x)
except ValueError:
return x
Example:
>>> [try_int(x) for x in ['sam', '1', 'dad', '21']]
['sam', 1, 'dad', 21]
Edit: If you need to apply the above to a list of lists, why didn't you converted those strings to int while building the nested list?
Anyway, if you need to, it's just a matter of choice on how to iterate over such nested list and apply the method above.
One way for doing that, might be:
>>> list_of_lists = [['aa', '2'], ['bb', '3']]
>>> [[try_int(x) for x in lst] for lst in list_of_lists]
[['aa', 2], ['bb', 3]]
You can obviusly reassign that to list_of_lists:
>>> list_of_lists = [[try_int(x) for x in lst] for lst in list_of_lists]
How about using map and lambda
>>> map(lambda x:int(x) if x.isdigit() else x,['sam','1','dad','21'])
['sam', 1, 'dad', 21]
or with List comprehension
>>> [int(x) if x.isdigit() else x for x in ['sam','1','dad','21']]
['sam', 1, 'dad', 21]
>>>
As mentioned in the comment, as isdigit may not capture negative numbers, here is a refined condition to handle it notable a string is a number if its alphanumeric and not a alphabet :-)
>>> [int(x) if x.isalnum() and not x.isalpha() else x for x in ['sam','1','dad','21']]
['sam', 1, 'dad', 21]
I would create a generator to do it:
def intify(lst):
for i in lst:
try:
i = int(i)
except ValueError:
pass
yield i
lst = ['sam','1','dad','21']
intified_list = list(intify(lst))
# or if you want to modify an existing list
# lst[:] = intify(lst)
If you want this to work on a list of lists, just:
new_list_of_lists = map(list, map(intify, list_of_lists))
For multidimenson lists, use recursive technique may help.
from collections import Iterable
def intify(maybeLst):
try:
return int(maybeLst)
except:
if isinstance(maybeLst, Iterable) and not isinstance(lst, str):
return [intify(i) for i in maybeLst] # here we call intify itself!
else:
return maybeLst
maybeLst = [[['sam', 2],'1'],['dad','21']]
print intify(maybeLst)
Use isdigit() to check each character in the string to see if it is a digit.
Example:
mylist = ['foo', '3', 'bar', '9']
t = [ int(item) if item.isdigit() else item for item in mylist ]
print(t)
Use a list comprehension to validate the numeracy of each list item.
str.isnumeric won't pass a negative sign
Use str.lstrip to remove the -, check .isnumeric, and convert to int if it is.
Alternatively, use str.isdigit in place of .isnumeric.
Keep all values in the list
l = ['sam', '1', 'dad', '21', '-10']
t = [int(v) if v.lstrip('-').isnumeric() else v for v in l]
print(t)
>>> ['sam', 1, 'dad', 21, -10]
Remove non-numeric values
l = ['sam', '1', 'dad', '21', '-10']
t = [int(v) for v in t if v.lstrip('-').isnumeric()]
print(t)
>>> [1, 21, -10]
Nested list
l = [['aa', '2'], ['bb', '3'], ['sam', '1', 'dad', '21', '-10']]
t = [[int(v) if v.lstrip('-').isnumeric() else v for v in x] for x in l]
print(t)
>>> [['aa', 2], ['bb', 3], ['sam', 1, 'dad', 21, -10]]

Categories