List comprehension replacing items that are not fl

2019-02-20 18:53发布

问题:

I have a 2 item list.

Sample inputs:

['19(1,B7)', '20(1,B8)']
['16 Hyp', '16 Hyp']
['< 3.2', '38.3302615548213']
['18.6086945477694', '121.561539536844']

I need to look for anything that isn's a float or an int and remove it. So what I need the above list to look like is:

['19(1,B7)', '20(1,B8)']
['16 Hyp', '16 Hyp']
['3.2', '38.3302615548213']
['18.6086945477694', '121.561539536844']

I wrote some code to find '> ' and split the first item but I am not sure how to have my 'new item' take the place of the old:

Here is my current code:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

for i in range(0,len(result_rows)):
    out_row = []
    for j in range(0,len(result_rows[i])-1):
        values = result_rows[i][j].split('+')
            for items in values:
                if '> ' in items:
                newItem=items.split()
                for numberOnly in newItem:
                   if is_number(numberOnly):
                      values.append(numberOnly)

The output of this (print(values)) is

['< 3.2', '38.3302615548213', '3.2']

回答1:

This looks more like a true list comprehension way to do what you want...

def isfloat(string):
    try:
        float(string)
        return True
    except:
        return False

[float(item) for s in mylist for item in s.split() if isfloat(item)]
#[10000.0, 5398.38770002321]

Or remove the float() to get the items as strings. You can use this list comprehension only if '>' or '<' are found in the string.



回答2:

What about

def stip_chars(lst):
    for item in lst:
        yield item.strip("> ")

new_values = [v for v in strip_chars(values) if is_number(v)]

?



回答3:

If you want to edit the list in place rather than create a new list, you can iterate over it using enumerate:

for (list_index, item) in enumerate(values):
    if '> ' in item:
        values[list_index] = ' '.join(item_part for item_part in item.split() if is_number(item_part))

Or however you want to construct your new value - I'm not sure what you want if you have '5 6' in your original list.

If you want a new list, you can do something similar with a list comprehension.



回答4:

values = ['> 10000', '5398.38770002321']
print [filter(lambda s: s in '0123456789.', v) for v in values]

RETURNS:

['10000', '5398.38770002321']

List of strings, as requested.

And to make it a function:

def parse_number(value):
    return [filter(lambda s: s in '0123456789.', v) for v in values]

print parse_number(values)

As an added bonus, making this accept negative numbers would be as easy as adding a hyphen to the whitelisted string '0123456789.-'



回答5:

Iterators work well here:

def numbers_only(l):
    for item in l:
        if '> ' in item:
            item = item.split()[1]
        try:
            yield float(item)
        except ValueError:
            pass
>>> values = ['> 10000', '5398.38770002321']
>>> list(numbers_only(values))
[10000.0, 5398.38770002321]

Normally, it's easier to create a new list than it is to iterate and modify the old list