Помогите мне упростить этот код (Python) - PullRequest
1 голос
/ 04 августа 2011

Я новичок в Python, учусь на Google Code University.У меня была эта проблема в качестве упражнения, и я смог решить ее, используя решение, показанное ниже:

# F. front_back
# Consider dividing a string into two halves.
# If the length is even, the front and back halves are the same length.
# If the length is odd, we'll say that the extra char goes in the front half.
# e.g. 'abcde', the front half is 'abc', the back half 'de'.
# Given 2 strings, a and b, return a string of the form
#  a-front + b-front + a-back + b-back
def front_back(a, b):
  if len(a) % 2 == 0:
    ad = len(a) / 2
    if len(b) % 2 == 0:
      bd = len(b) / 2
    else:
      bd = (len(b) / 2) + 1
  else:
    ad = (len(a) / 2) + 1
    if len(b) % 2 == 0: 
      bd = len(b) / 2
    else:
      bd = (len(b) / 2) + 1

  return a[:ad] + b[:bd] + a[ad:] + b[bd:]

Это дает правильный вывод и решает проблему.Тем не менее, я дублирую логику того, нужно ли разделять строку равномерно или добавить нечетное число к первой половине, и это кажется излишним.Должен быть более эффективный способ сделать это.Та же самая точная проверка и логика применяются к a и b.Кто-нибудь? * * 1004

Ответы [ 7 ]

12 голосов
/ 04 августа 2011
def front_back(a, b):
    ad = (len(a) + 1) // 2
    bd = (len(b) + 1) // 2
    return a[:ad] + b[:bd] + a[ad:] + b[bd:]

Использование // для деления заставляет этот код работать как в Python 2.x, так и 3.x.

4 голосов
/ 04 августа 2011

Ну, поместите это в отдельную функцию.

def front_back(string):
    offset = len(string) / 2
    if len(string) % 2 != 0:
        offset += 1
    return string[:offset], string[offset:]

def solution(a, b):
    front_a, back_a = front_back(a)
    front_b, back_b = front_back(b)
    return front_a + back_a + front_b + back_b
3 голосов
/ 04 августа 2011

Поскольку вы добавляете 1 к длине, если она нечетная, а 'нечетная' означает, что len(a)%2 == 1 ...

def front_back2(a, b):
    ad = (len(a) + len(a)%2) / 2
    bd = (len(b) + len(b)%2) / 2
    return a[:ad]+b[:bd]+a[ad:]+b[bd:]

Конечно, вы можете даже сжать его до одной строки только для ударов (хотя, это значительно менее читабельно):

def front_back2(a, b):
    return a[:(len(a)+len(a)%2)/2]+b[:(len(b)+len(b)%2)/2]+a[(len(a)+len(a)%2)/2:]+b[(len(b)+len(b)%2)/2:]
2 голосов
/ 05 августа 2011

Мхх, пытаясь понять @ Свен ответ Я получил это:

len( s ) + 1 / 2 

Всегда даст вам правильный индекс.

Итак, если мы поместим это в функцию:

def d( s ):
   return ( len(s) + 1 ) / 2

Мы можем использовать это в решении:

def front_back( a, b ): 
    return a[:d(a)] + b[:d(b)] + a[d(a):] + b[d(b):]

Хорошо, я получил это сейчас.*

Я не совсем уверен, в чем разница между / и // хотя

2 голосов
/ 04 августа 2011

Максимальный индекс можно получить с помощью ceil

In [1]: l = [1,2,3]
In [2]: import math
In [4]: math.ceil(len(l)/2.0)
Out[4]: 2.0
In [5]: l.append(4)
In [6]: math.ceil(len(l)/2.0)
Out[6]: 2.0
In [7]: l.append(5)
In [8]: math.ceil(len(l)/2.0)
Out[8]: 3.0
In [9]: l[0:3]
Out[9]: [1, 2, 3]
In [10]: l[3:]
Out[10]: [4, 5]
1 голос
/ 04 августа 2011

Вот мой:

def front_back( a, b ) :
    return of(a)[0] + of(b)[0] + of(a)[1] + of(b)[1]

def of( s ):
   index = len( s ) / 2 + ( 1 if len( s ) % 2 == 1 else 0 )
   return ( s[ : index ] , s[ index : ] )


print front_back('abcde','hola')

Отпечатки:

abchodela
1 голос
/ 04 августа 2011
from math import ceil

def front_back(a, b):
    divide = lambda s: int(ceil(len(s) / 2.0)) # or lambda s: (len(s) + 1) // 2
    a_divide, b_divide = divide(a), divide(b)
    return a[:a_divide] + b[:b_divide] + a[a_divide:] + b[b_divide:]
...