2017-11-23 2 views
0

文字列(数字、文字、特殊記号など)を受け取る関数を定義し、文字列のすべての桁を考慮して計算された平均を含む1つの浮動小数点数を返します文字列の最後の位置から始まり、1文字が見つかるまで、または文字列の先頭に到達するまで(後方に進む)、文字列の先頭に到達するまで(数字の場合は文字列の最初の文字を計算に含める)。文字列に数字がない場合、または最初の数字が見つかる前に文字が見つかった場合、関数は値0.0を返します。逆方向に移動している文字列の平均を見つける

たとえば、4と3の平均が3.5であるため、avgBackw( " - 1 --- 2 - A - 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) 
+0

だから、あなたは合計を追跡するために必要な平均値を取得したい場合あなたが遭遇した桁数。 '.isdigit()'と '.isalpha()'を使って、文字が数字か文字かを調べることができます。数字に遭遇すると、その値を合計に記録し、手紙に出会うと、ループから脱出します。ループを終えたら、平均値を返します。これは、合計と桁数を使用して計算できます。数字がない場合は必ず考慮してください。そうでない場合は、ゼロで除算されます。 – user2896976

+0

avgBackw( " - 1 --- 2 - A - 3--04--")のような特別な場合は、(40 + 3)/ 2 = 21.5を生成すると仮定して、またはちょうど3.5 – Gumboy

+0

私たちが--A-1--45--4のような連続した数字を持つときはどうでしょうか? –

答えて

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 
+0

私は 'float(sum/count)'の目的を見ません。あなたがPython 2とPython 3の互換性を試していると仮定して、 'sum/float(count)'を実行します。 – cdlane

+0

この解決策では、文字ターミネータが必要であると想定しています。 '-5 --- 4--3--2--1 - 'であれば、平均の代わりにゼロを返します。簡単な修正。 – cdlane

+0

@cdlane提案をいただき、ありがとうございました。私は私のソリューションを更新しました。 –

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--") 
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 
+1

問題のOPの説明に '-A --- 4-c-2--1--- avg:2.33'を説明できますか?私は '-A --- 4-A-2--1---> avg:1.5'とどのように違うのか分かりません。ありがとうございました。 – cdlane

+0

このエラーを指摘してくれた@cdlaneに感謝します。 find_sepで 'a'を取り消すだけです。最後の編集を参照してください。背後にあるアイデアは、逆の文字列の最初の文字を見つけ、この文字列で文字列を分割し、すべての数字を見つけ出し、合計してその平均を見つけることです。 –

+1

手紙は文字(または文字列の終わり)が処理を停止するが、あなたのコードは他の句読点で停止することが明確だった。 '-5-Z-4- + 3--2--1-> avg:2.0' – cdlane

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 
関連する問題