How to compare strings containing numbers in a list? - python

how do I delete a row of strings containing numbers bigger than a certain threshold from a list.
I want my threshold to be more than 60, since it's impossible for songs to have a duration of 4:63 (4 mins 63 secs)
List before being filtered:
[['4:63', ' Test', 'Results'], ['A', 'B', 'C'], ['D', '4:20', 'F']]
Intended List after being filtered:
[['A', 'B', 'C'], ['D', '4:20', 'F']]
So basically my question is: how do I identify inside a list of list, and delete the rows for the strings containing a number bigger than 60.
My code:
def get_csv_as_table(a, b):
import csv
with open(a) as csv_file:
file_reader = csv.reader(csv_file, delimiter=b)
member = list(file_reader)
for i in range(len(member)):
for j in range(len(member)):
if member[i][j].isdigit():
member[i][j] = int(member[i][j])
print(member)
return member
def filter_table(member):
clean_sample_data = [row for row in member if not "" in row]
print(clean_sample_data)
member = []
print ("Enter filename: ")
a = input()
print ("Enter the delimiter: ")
b = input()
member = get_csv_as_table(a, b)
filter_table(member)

You can use a regex to get all the numbers and then use any() to check that none of them are above 60 in a list comprehension:
import re
lst = [['4:63', ' Test', 'Results'], ['A', 'B', 'C'], ['D', '4:20', 'F']]
filtered_lst = [
sub_lst
for sub_lst in lst
if not any(x > 60 for x in map(int, re.findall(r'\d+', ''.join(sub_lst))))
]
print(filtered_lst)
Output:
[['A', 'B', 'C'], ['D', '4:20', 'F']]

One way letting datetime.strptime to judge:
import re
from datetime import datetime
matcher = lambda x: re.match("\d+:\d+", x)
def is_validtime(str_):
if matcher(str_):
try:
ms = datetime.strptime(str_, "%M:%S")
except:
return False
return True
[i for i in l if all(is_validtime(j) for j in i)]
Output:
[['A', 'B', 'C'], ['D', '4:20', 'F']]

Related

A simple question about regex usage in list

I have a list in list as ''list_all'' below, I am looking for a word as stated 'c' below. Ther is no 'c' in second list. Codes below give results as ['c', 'c'] but I want to have ['c', '', 'c'] as to be same lenght 'list_all'. Could you please help me on it how can I put empty element to result.
import re
list_all = [['a','b','c','d'],['a','b','d'],['a','b','c','d','e']]
listofresult =[]
for h in [*range(len(list_all))]:
for item in list_all[h]:
patern = r"(c)"
if re.search(patern, item):
listofresult.append(item)
else:
None
print(listofresult)
try this
import re
list_all = [['a','b','c','d'],['a','b','d'],['a','b','c','d','e']]
temp = True
listofresult =[]
for h in range(len(list_all)):
for item in list_all[h]:
patern = r"(c)"
if re.search(patern, item):
listofresult.append(item)
temp = False
if temp:
listofresult.append("")
temp = True
print(listofresult)
That's an unusual use of regex! but if you insist, this correction might help:
import re
list_all = [['a', 'b', 'c', 'd'], ['a', 'b', 'd'], ['a', 'b', 'c', 'd', 'e']]
list_of_result = []
for h in list_all:
result = ''
for item in h:
pattern = r"(c)"
if re.search(pattern, item):
result = item
break
if result:
list_of_result.append(result)
else:
list_of_result.append('')
print(list_of_result)

Split a list in python with an element as the delimiter? [duplicate]

This question already has answers here:
Python split for lists
(6 answers)
Closed 2 years ago.
I want to create sub-lists from a list which has many repeating elements, ie.
l = ['a', 'b', 'c', 'c', 'b', 'a', 'b', 'c', 'b', 'a']
Wherever the 'a' begins the list should be split. (preferably removing 'a' but not a must)
As such:
l = [ ['b', 'c', 'c', 'b'], ['b', 'c', 'b'] ]
I have tried new_list = [x.split('a')[-1] for x in l] but I am not getting the desired "New list" effect.
When you write,
new_list = [x.split('a')[-1] for x in l]
you are essentially performing,
result = []
for elem in l:
result.append(elem.split('a')[-1])
That is, you're splitting each string contained in l on the letter 'a', and collecting the last element of each of the strings into the result.
Here's one possible implementation of the mechanic you're looking for:
def extract_parts(my_list, delim):
# Locate the indices of all instances of ``delim`` in ``my_list``
indices = [i for i, x in enumerate(my_list) if x == delim]
# Collect each end-exclusive sublist bounded by each pair indices
sublists = []
for i in range(len(indices)-1):
part = my_list[indices[i]+1:indices[i+1]]
sublists.append(part)
return sublists
Using this function, we have
>>> l = ['a', 'b', 'c', 'c', 'b', 'a', 'b', 'c', 'b', 'a']
>>> extract_parts(l, 'a')
[['b', 'c', 'c', 'b'], ['b', 'c', 'b']]
You can use zip and enumerate to do that. Create a list of ids for separation and just break it at those points.
size = len(l)
id_list = [id + 1 for id, val in
enumerate(test_list) if val == 'a']
result = [l[i:j] for i, j in zip([0] + id_list, id_list +
([size] if id_list[-1] != size else []))]
It will not include the delimiter
import itertools
lst = ['a', 'b', 'c', 'c', 'b', 'a', 'b', 'c', 'b', 'a']
delimiter = lst[0]
li=[list(value) for key,value in itertools.groupby(lst, lambda e: e == delimiter) if not key]
print(li)
Explanation: groupby function will create a new group each time key will change
Key value
True itertools._grouper object pointing to group 'a'
False itertools._grouper object pointing to group 'b', 'c', 'c', 'b'
True itertools._grouper object pointing to group 'a'
False itertools._grouper object pointing to group 'b', 'c', 'b'
True itertools._grouper object pointing to group 'a'
In if condition checking if the key is false, return the itertools._grouper object and then pass itertool object to list.
Create a counters array for each element you want to split at then write a condition in this fashion:
l = ['a', 'b', 'c', 'c', 'b', 'a', 'b', 'c', 'b', 'a']
counters = [0,0,0] #to count instances
index = 0 #index of l
startIndex = 0 #where to start split
endIndex = 0 #where to end split
splitLists = [] #container for splits
for element in l:
if element == 'a': #find 'a'
counters[0] += 1 #increase counter
if counters[0] == 1: #if first instance
startIndex = index + 1 #start split after
if counters[0] == 2:
endIndex = index #if second instance
splitList = l[startIndex:endIndex] #end split here
counters[0] = 1 #make second starting location
startIndex = index + 1
splitLists.append(splitList) #append to main list of lists
index += 1
print(splitLists)
So basically you are finding the start and end index of the matching pattern within the list. You use these to split the list, and append this list into a main list of lists (2d list).

Splitting a python list into smaller lists at spaces

I have a list which consists of alphabets and spaces:
s = ['a','b',' ',' ','b','c',' ','d','e','f','g','h',' ','i','j'];
I need to split it into smaller individual lists:
s=[['a','b'],['b','c'],['d','e','f','g','h'],['i','j']]
I am new to python.
The entire code:
#To get the longest alphabetical substring from a given string
s = input("Enter any string: ")
alpha_string = []
for i in range(len(s)-1): #if length is 5: 0,1,2,3
if(s[i] <= s[i+1]):
if i == len(s)-2:
alpha_string.append(s[i])
alpha_string.append(s[i+1])
else:
alpha_string.append(s[i])
if(s[i] > s[i+1] and s[i-1] <= s[i]):
alpha_string.append(s[i])
alpha_string.append(" ")
if(s[i] > s[i+1] and s[i-1] > s[i]):
alpha_string.append(" ")
print(alpha_string)
#Getting the position of each space in the list
position = []
for j in range(len(alpha_string)):
if alpha_string[j] == " ":
position.append([j])
print(position)
#Using the position of each space to create slices into the list
start = 0
final_string = []
for k in range(len(position)):
final_string.append(alpha_string[start:position[k]])
temp = position[k]
start = temp
print(final_string)`
Try a list comprehension as follows
print([list(i) for i in ''.join(s).split(' ') if i != ''])
[['a', 'b'], ['b', 'c'], ['d', 'e', 'f', 'g', 'h'], ['i', 'j']]
Here generator will be perfect :
s = ['a','b',' ',' ','b','c',' ','d','e','f','g','h',' ','i','j'];
def generator_approach(list_):
list_s=[]
for i in list_:
if i==' ':
if list_s:
yield list_s
list_s=[]
else:
list_s.append(i)
yield list_s
closure=generator_approach(s)
print(list(closure))
output:
[['a', 'b'], ['b', 'c'], ['d', 'e', 'f', 'g', 'h'], ['i', 'j']]
Or simply in one line, result = [list(item) for item in ''.join(s).split()]
This is one functional way.
s = ['a','b',' ',' ','b','c',' ','d','e','f','g','h',' ','i','j']
res = list(map(list, ''.join(s).split()))
# [['a', 'b'], ['b', 'c'], ['d', 'e', 'f', 'g', 'h'], ['i', 'j']]
from itertools import groupby
s = ['a','b',' ',' ','b','c',' ','d','e','f','g','h',' ','i','j']
t = [list(g) for k, g in groupby(s, str.isspace) if not k]
print(t)
OUTPUT
[['a', 'b'], ['b', 'c'], ['d', 'e', 'f', 'g', 'h'], ['i', 'j']]
This doesn't require the strings to be single letter like many of the join() and split() solutions:
>>> from itertools import groupby
>>>
>>> s = ['abc','bcd',' ',' ','bcd','cde',' ','def','efg','fgh','ghi','hij',' ','ijk','jkl']
>>>
>>> [list(g) for k, g in groupby(s, str.isspace) if not k]
[['abc', 'bcd'], ['bcd', 'cde'], ['def', 'efg', 'fgh', 'ghi', 'hij'], ['ijk', 'jkl']]
>>>
I can never pass up an opportunity to (ab)use groupby()

How to repeat an operation on a list

I want to have a list of 4-letters, then I want to pick two elements of it randomly, merge them together, and add it as a new element to the original list. This way I make a new list. Now I want to repeat the same procedure from the new list, meaning taking two elements from the new list randomly merge them together and make a new list again. So far I did the first step:
import random
num = 2
aList = ['A','B','C','D']
newList = []
newList+=random.sample(aList, num)
L = [''.join(newList[0:2])]+aList
print(L)
I wonder how to repeat the procedure say 5 more times.
Try this out
import random
aList = ['A','B','C','D']
for i in range(5): aList.append(''.join(random.sample(aList, num)))
print(aList)
Mya be you can create a method :
import random
num = 2
aList = ['A','B','C','D']
def randomizeList(list):
newList = []
newList+=random.sample(list, num)
L = [''.join(newList[0:2])]+list
return L
Now u call this method as many times as you want:
list = randomizeList(randomizeList(randomizeList(randomizeList(aList))))
or
list1 = randomizeList(aList)
list2 = randomizeList(list1)
list3 = randomizeList(list2)
and ......
By creating a function:
import random
def randMerge(l:list, count:int) -> list:
"""Returns the input list expanded by a joined element consisting of
count elements from itself (no repeats allowed)"""
return l + [''.join(random.sample(l,k=count))]
and calling it repeatedly:
num = 2
aList = ['A','B','C','D']
newList = aList[:]
for _ in range(6):
print(newList)
newList = randMerge(newList,num)
print(newList)
Output:
['A', 'B', 'C', 'D']
['A', 'B', 'C', 'D', 'DC']
['A', 'B', 'C', 'D', 'DC', 'ADC']
['A', 'B', 'C', 'D', 'DC', 'ADC', 'CD']
['A', 'B', 'C', 'D', 'DC', 'ADC', 'CD', 'CDA']
['A', 'B', 'C', 'D', 'DC', 'ADC', 'CD', 'CDA', 'CDC']
['A', 'B', 'C', 'D', 'DC', 'ADC', 'CD', 'CDA', 'CDC', 'ADCCDC']
Try this
import random
def randomoperation():
num = 2
aList = ['A', 'B', 'C', 'D']
newList = []
newList += random.sample(aList, num)
L = [''.join(newList[0:2])]+aList
return L
for i in range(5):
print randomoperation()

How to create nested list from flatten list?

I wrote a function to create a nested list.
For example:
input= ['a','b','c','','d','e','f','g','','d','s','d','a','']
I want to create a sublist before ''
As a return I want a nested list like:
[['a','b','c'],['d','e','f','g'],['d','s','d','a']]
Try the following implementation
>>> def foo(inlist, delim = ''):
start = 0
try:
while True:
stop = inlist.index(delim, start)
yield inlist[start:stop]
start = stop + 1
except ValueError:
# if '' may not be the end delimiter
if start < len(inlist):
yield inlist[start:]
return
>>> list(foo(inlist))
[['a', 'b', 'c'], ['d', 'e', 'f', 'g'], ['d', 's', 'd', 'a']]
Another possible implementation could be by itertools.groupby. But then you have to filter the result to remove the ['']. But though it might look to be one-liner yet the above implementation is more pythonic as its intuitive and readable
>>> from itertools import ifilter, groupby
>>> list(ifilter(lambda e: '' not in e,
(list(v) for k,v in groupby(inlist, key = lambda e:e == ''))))
[['a', 'b', 'c'], ['d', 'e', 'f', 'g'], ['d', 's', 'd', 'a']]
I'd use itertools.groupby:
l = ['a','b','c','','d','e','f','g','','d','s','d','a','']
from itertools import groupby
[list(g) for k, g in groupby(l, bool) if k]
gives
[['a', 'b', 'c'], ['d', 'e', 'f', 'g'], ['d', 's', 'd', 'a']]
def nester(nput):
out = [[]]
for n in nput:
if n == '':
out.append([])
else:
out[-1].append(n)
if out[-1] == []:
out = out[:-1]
return out
edited to add check for empty list at end

Categories