2015-05-31 4 views
1

А «pyschool» упражнение:добавление специфических элементов списка питона

«Определение функции вызывает addFirstAndLast(x), который принимает в списке чисел и возвращает сумму первого и последнего числа.»

Вот лучшее решение, которое я придумал. Есть ли более элегантный способ написать эту функцию, которая также использует только встроенные функции?

def addFirstAndLast(x): 
    sum_list = [] 
    if len(x) == 0: 
     return 0 
    elif len(x) == 1 : 
     return int(x[0]) 
    elif len(x) > 1 : 
     sum_list.append(x[0]) 
     sum_list.append(x[-1]) 
    return sum(sum_list) 
+3

'return x [0] + x [-1]' для последнего случая. Нет необходимости создавать новый список как 'sum_list', а затем применять' sum() ', если у вас действительно есть только 2 номера для добавления. – ZdaR

ответ

2
>>> def addFirstAndLast(x): 
... return (x[0]+x[-1])/(1/len(x)+1) if x else 0 
... 
>>> addFirstAndLast([]) 
0 
>>> addFirstAndLast([1]) 
1 
>>> addFirstAndLast([1,3]) 
4 

Примечание 1: только тогда, когда длина списка 1 результат (1/len(x)+1) является 2, так что вы разделите сумму первого и последнего элементов на 2 остальных это разделить на 1.

Примечание 2: если вы находитесь на питоне 3, используйте // для разделения вместо /.

+1

Это обрабатывает все тестовые примеры., отлично :) – ZdaR

+0

Немного запутанная логика ... и разве вы не должны использовать '//' для целочисленного деления? –

+0

@ PM2Ring В python 3 да, но в этом случае нет необходимости, потому что OP ** принял ** ответ! – Kasramvd

0
def addFirstAndLast(x): 
    if x: 
     return sum(zip(*filter(lambda (i,s): i == 0 or i == len(x) - 1, enumerate(x)))[1]) 
    else: 
     return 0 

Перечислите элементы в списке, отфильтруйте, разархивируйте, а затем верните сумму.

2

Ответ Kasra намного лучше, но это немного другой способ сделать это. Поскольку x[0] всегда возвращается, если он существует, вы можете просто проверить, нужно ли добавить x[-1].

def firstAndLast(x): 
    if x: 
     value = x[0] 
     if len(x)>1: 
      value += x[-1] 
     return value 
    return 0 
+0

Ваш код легче понять, чем у Касры, и не выполняет 2 таинственных подразделения. –

0

Используйте расширенную нотацию фрагмента, с max, чтобы обрабатывать пустой список.

for i in range(5): 
    a = range(10, 10 + i) 
    b = a[::max(1, len(a)-1)] 
    print a, b, sum(b) 

выход

[] [] 0 
[10] [10] 10 
[10, 11] [10, 11] 21 
[10, 11, 12] [10, 12] 22 
[10, 11, 12, 13] [10, 13] 23 

А вот версия, которая делает это в функции.

def add_first_and_last(x): 
    return sum(x[::max(1, len(x)-1)]) 

for i in range(5): 
    a = range(10, 10 + i) 
    print a, add_first_and_last(a) 

выход

[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 

В Kasra-х побуждая я сделал некоторые временные испытания основных существующих ответов. Я также добавил модифицированную версию алгоритма Питера, которая немного быстрее.

from timeit import Timer 

def addFirstAndLast_Sam(x): 
    sum_list = [] 
    if len(x) == 0: 
     return 0 
    elif len(x) == 1 : 
     return int(x[0]) 
    elif len(x) > 1 : 
     sum_list.append(x[0]) 
     sum_list.append(x[-1]) 
    return sum(sum_list) 

def add_first_and_last_PM2Ring_slow(x): 
    return sum(x[::max(1, len(x)-1)]) 

def add_first_and_last_PM2Ring_fast(x): 
    return x[0] + x[-1] if len(x) > 1 else x[0] if x else 0 

def firstAndLast_Peter(x): 
    if x: 
     value = x[0] 
     if len(x)>1: 
      value += x[-1] 
     return value 
    return 0 

def addFirstAndLast_Kasra(x): 
    return (x[0] + x[-1]) // (1 // len(x) + 1) if x else 0 

funcs = (
    add_first_and_last_PM2Ring_fast, 
    firstAndLast_Peter, 
    addFirstAndLast_Kasra, 
    add_first_and_last_PM2Ring_slow, 
    addFirstAndLast_Sam, 
) 

num = 10 
lists = [range(10, 10 + i) for i in range(num + 1)] 

def verify(): 
    ''' Verify that the functions actually perform as intended ''' 
    print 'Verifying...' 
    for func in funcs: 
     fname = func.func_name 
     print '\n%s' % fname 
     for a in lists: 
      print a, func(a) 

def time_test(loops, reps): 
    ''' Print timing stats for all the functions ''' 
    print '\nTiming tests\nLoops = %d, Repetitions = %d' % (loops, reps) 

    for func in funcs: 
     fname = func.func_name 
     print '\n%s' % fname 
     setup = 'from __main__ import lists, %s' % fname 
     t = Timer('[%s(a) for a in lists]' % fname, setup) 
     r = t.repeat(reps, loops) 
     r.sort() 
     print r 

verify() 
time_test(loops=10000, reps=3) 

выход

Verifying... 

add_first_and_last_PM2Ring_fast 
[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 
[10, 11, 12, 13, 14] 24 
[10, 11, 12, 13, 14, 15] 25 
[10, 11, 12, 13, 14, 15, 16] 26 
[10, 11, 12, 13, 14, 15, 16, 17] 27 
[10, 11, 12, 13, 14, 15, 16, 17, 18] 28 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 29 

firstAndLast_Peter 
[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 
[10, 11, 12, 13, 14] 24 
[10, 11, 12, 13, 14, 15] 25 
[10, 11, 12, 13, 14, 15, 16] 26 
[10, 11, 12, 13, 14, 15, 16, 17] 27 
[10, 11, 12, 13, 14, 15, 16, 17, 18] 28 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 29 

addFirstAndLast_Kasra 
[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 
[10, 11, 12, 13, 14] 24 
[10, 11, 12, 13, 14, 15] 25 
[10, 11, 12, 13, 14, 15, 16] 26 
[10, 11, 12, 13, 14, 15, 16, 17] 27 
[10, 11, 12, 13, 14, 15, 16, 17, 18] 28 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 29 

add_first_and_last_PM2Ring_slow 
[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 
[10, 11, 12, 13, 14] 24 
[10, 11, 12, 13, 14, 15] 25 
[10, 11, 12, 13, 14, 15, 16] 26 
[10, 11, 12, 13, 14, 15, 16, 17] 27 
[10, 11, 12, 13, 14, 15, 16, 17, 18] 28 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 29 

addFirstAndLast_Sam 
[] 0 
[10] 10 
[10, 11] 21 
[10, 11, 12] 22 
[10, 11, 12, 13] 23 
[10, 11, 12, 13, 14] 24 
[10, 11, 12, 13, 14, 15] 25 
[10, 11, 12, 13, 14, 15, 16] 26 
[10, 11, 12, 13, 14, 15, 16, 17] 27 
[10, 11, 12, 13, 14, 15, 16, 17, 18] 28 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 29 

Timing tests 
Loops = 10000, Repetitions = 3 

add_first_and_last_PM2Ring_fast 
[0.15383195877075195, 0.15486502647399902, 0.18578314781188965] 

firstAndLast_Peter 
[0.16625690460205078, 0.16726803779602051, 0.17240190505981445] 

addFirstAndLast_Kasra 
[0.19242000579833984, 0.19251012802124023, 0.21216797828674316] 

add_first_and_last_PM2Ring_slow 
[0.38388991355895996, 0.39070892333984375, 0.39607501029968262] 

addFirstAndLast_Sam 
[0.38914084434509277, 0.38966894149780273, 0.41235685348510742] 

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

+0

Нет необходимости использовать 'sum' и' max' и 'len' для этой простой задачи !!! вы просто делаете это очень неэффективным! – Kasramvd

+0

@ Kasra: Я согласен, что этот подход медленнее вашего. OTOH, код Питера быстрее, чем у нас. Я отправлю некоторые тесты времени. –

Смежные вопросы