向后寻找字符串的平均值

时间:2017-11-23 02:52:52

标签: python loops while-loop average

我需要定义一个接收字符串(可能包含数字,字母和/或特殊符号)的函数,并返回一个包含平均值的浮点数,考虑字符串中最后一个位置开始的字符串中的所有数字,考虑所有数字(向后)直到找到一个字母或直到到达字符串的开头(如果它是一个数字,则包括字符串中的第一个字符用于计算)。如果字符串中没有数字,或者在找到第一个数字之前找到了一个字母,那么该函数应返回值0.0。

例如,avgBackw(“ - 1 --- 2 - A - 3--4--”)应该返回3.5,因为4和3的平均值是3.5。

As an example, the following code fragment:

value = avgBackw("-1---2--A--3--4--")
print(value)

should produce the output:

3.5

这是我到目前为止最远的...我不知道从哪里开始..

def avgBackw(lst): 
  rv = []  
  for n in lst[::-1]: 
    try:
        rv.append(int(lst))
    except:
        return len(rv)
return len(rv)

4 个答案:

答案 0 :(得分:0)

使用isalpha()isdigit()

def avgBack(string):
    sum, count =  0.0, 0
    for s in string[::-1]:
        if s.isalpha():
            break
        if s.isdigit():
            sum += int(s)
            count+=1
    return float(sum/count) if count else 0

答案 1 :(得分:0)

您需要做的是:

1。删除除数字和字母之外的所有字符

2。反转已剥离的列表

3. 检查基本情况

4. 计算找到字符前所有数字的平均值

这是一种蛮力方法(没有有用的库函数):

def average_back(string):
    # sum count for average
    count = 0
    sums = 0.0

    # strip the string except for the digits and letters
    stripped = []
    for char in string:
        if char.isdigit() or char.isalpha():
            stripped.append(char)

    # reverse the string
    reverse = stripped[::-1]

    # if list is empty, of no digits are found, or the first letter is a letter
    if not reverse or not has_number(reverse) or reverse[0].isalpha():
        return sums

    # loop until character is found
    for char in reverse:
        if char.isalpha():
            break
        else:
            sums += float(char)
            count += 1

    # return average
    return sums / count

def has_number(string):
    for char in string:
        if (char.isdigit()):
            return True

    return False

使用更高阶函数的另一个更简洁(可以改进)的实现,例如map()any()itertools.takewhile()str.join()

from itertools import takewhile

def average_back2(string):

    # strip the string except for the digits and letters
    stripped = "".join(x for x in string if x.isalpha() or x.isdigit())

    # reverse the string
    reverse = stripped[::-1]

    # if list is empty, of no digits are found, or the first letter is a letter
    if not reverse or not any(x.isdigit() for x in reverse) or reverse[0].isalpha():
        return 0.0

    # concatenate numbers until non-digit is found
    valid_numbers = "".join(takewhile(lambda x : not x.isalpha(), reverse))

    # convert string to list of integers
    numbers = list(map(int, valid_numbers))

    # return sum
    return sum(numbers) / len(numbers)

其工作原理如下:

>>> average_back("-1---2--A--3--4--")
3.5
>>> average_back2("-1---2--A--3--4--")
3.5
>>> average_back("-1---2--A--3--A--")
0.0
>>> average_back2("-1---2--A--3--A--")
0.0
>>> average_back("-A---A--A--A--1--")
1.0
>>> average_back2("-A---A--A--A--1--")
1.0
>>> average_back("-A---A--A--A--A--")
0.0
>>> average_back2("-A---A--A--A--A--")
0.0
>>> average_back("-5---4--3--2--1--")
3.0
>>> average_back2("-5---4--3--2--1--")
3.0
>>> average_back("-A---4--3--2--1--")
2.5
>>> average_back2("-A---4--3--2--1--")
2.5
>>> average_back("-A---4--A--2--1--")
1.5
>>> average_back2("-A---4--A--2--1--")

答案 2 :(得分:0)

您可以使用regex来解决您的问题,如下例所示:(请参阅评论以了解引人注目的内容):

import re 

def find_sep(a):
    '''Find the separator which is anything except numbers and "-" '''
    # é, è, æ, etc ... are not a valid separators.
    # Otherwise, add them to the next line in the regex rule
    sep = re.findall(r'[a-zA-Z]', a[::-1])
    if sep:
        # Reverse the string
        # And take the first part of the string if we find a separator
        return a[::-1].split(sep[0])[0]
    else:
        # Return the string reversed
        return a[::-1]


def average_backwards(a):
    '''Reverse the string and calculate the average'''
    # Find the seperator if exists and return an inversed string with numbers if they exists
    b = find_sep(a)
    # Find all the numbers
    nums = re.findall(r'(\d+)', b[::-1])
    if nums:
        avg = round(sum(map(int, nums))/len(nums), 2)
        return avg
    return 0.0


# Test

nums = ["-1---2--b--3--04--", "-1---2--e--3--4--", "-1---2--A--3--A--", "-1---2--A--3----", 
        "-A---A--A--A--1--", "-A---A--A--+--1--", "-A---A--A--A--A--", "-A---2--A--A--A--", 
        "-5---4--3--2--1--", "-5-Z--4--3--2--1--", "-A---4--3------", "-A---4--c--2--1--", 
        "----4--A--2--1--", "-A---4--A--2--1--", "-5-Z--4-+3--2--1-"]


for num in nums:
    print('{0} -> avg: {1}'.format(num, average_backwards(num)))

输出:

-1---2--b--3--04-- => 3.5
-1---2--e--3--4-- => 3.5
-1---2--A--3--A-- => 0.0
-1---2--A--3---- => 3.0
-A---A--A--A--1-- => 1.0
-A---A--A--+--1-- => 1.0
-A---A--A--A--A-- => 0.0
-A---2--A--A--A-- => 0.0
-5---4--3--2--1-- => 3.0
-5-Z--4--3--2--1-- => 2.5
-A---4--3------ => 3.5
-A---4--c--2--1-- => 1.5
----4--A--2--1-- => 1.5
-A---4--A--2--1-- => 1.5
-5-Z--4-+3--2--1- => 2.5

答案 3 :(得分:0)

我永远不会错过在一个问题上抛出itertools.groupby的机会:

from itertools import groupby

def avgBackw(string):
    digits = list()

    for key, group in groupby(string[::-1], lambda c: c.isalnum() + c.isdigit()):

        if key == 1:  # we hit one or more letters
            break

        if key == 2: # we hit one or more digits
            digits += group

    return sum(map(int, digits)) / len(digits) if digits else 0