Наиболее питонический способ расширить потенциально неполный список - PullRequest
8 голосов
/ 05 февраля 2009

То, что я ищу, - лучший способ сказать: «Если этот список слишком короткий, удлините его до 9 элементов и добавьте« Выбор 4 »,« Выбор 5 »и т. Д. В качестве дополнительных элементов. Также замените все элементы «None» на «Choice x». Можно заменить "" и 0 тоже.

Примером преобразования будет

['a','b',None,'c']

до

['a','b','Choice 3','c','Choice 5','Choice 6','Choice 7','Choice 8','Choice 9']

В моем исходном коде неправильно использовалась попытка / исключение и произошла ошибка, которую я не заметил; спасибо Joeforker и всем, кто указал на это. На основании комментариев я попробовал два коротких решения, которые одинаково хорошо тестируют:

def extendChoices(cList):
  for i in range(0,9):
    try:
      if cList[i] is None:
        cList[i] = "Choice %d"%(i+1)
    except IndexError:
      cList.append("Choice %d"%(i+1)

и

def extendChoices(cList):
  # Fill in any blank entries
  for i, v in enumerate(cList):
    cList[i] = v or "Choice %s" % (i+1)

  # Extend the list to 9 choices  
  for j in range(len(cList)+1, 10):
    cList.append("Choice %s" % (j))

Я думаю, что # 2 побеждает как более питонический, поэтому я буду использовать его. Это легко понять и использует общие конструкции. Разделение шагов логично и облегчает понимание с первого взгляда.

Ответы [ 20 ]

1 голос
/ 05 февраля 2009

Как насчет этого (кажется, что это диктат, а не список), когда оно неполно )

a = {1:'a', 2:None, 5:'e'} #test data
[a[x] if x in a and a[x] is not None else 'Choice %d'%x for x in xrange(1,10)]

Отредактируйте еще раз: если это действительно список (не диктат):

b=['a',None,'b']
[b[x] if len(b)>x and b[x] is not None else 'Choice %d'%x for x in xrange(10)]

нужен Python 2.5, я думаю (из-за троичного оператора)?

(Благодаря joeforker исправлено, что он использует ключи от 1 до 10, а не от 0 до 10 больше; благодаря SilentGhost: in более питоничен, чем has_key () или len ())

1 голос
/ 05 февраля 2009

Вы могли бы пойти проще с пониманием списка:

extendedChoices = choices + ([None] * (10 - len(choices)))
newChoices = ["Choice %d" % (i+1) if x is None else x
    for i, x in enumerate(extendedChoices)]

Это добавляет None к вашему списку выбора, пока в нем не будет как минимум 10 элементов, перечисляет результат и вставляет «Выбор X», если элемент X отсутствует.

1 голос
/ 05 февраля 2009

Я считаю, что когда списки становятся длиннее, лучше просто использовать стандартный цикл for. Почти так же, как другие, но в любом случае:

>>> in_list = ["a","b",None,"c"]
>>> full_list = in_list + ([None] * (10 - len(in_list)))
>>> for idx, value in enumerate(full_list):
...     if value == None:
...             full_list[idx] = 'Choice %d' % (idx + 1)
...
>>> full_list
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9', 'Choice 10']
1 голос
/ 05 февраля 2009

Ну в одной строке:

[a or 'Choice %d' % i for a,i in map(None,["a","b",None,"c"],range(10))]

Хотя это заменит все, что оценивается как Ложное (например, Нет, '', 0 и т. Д.), На "Вариант n". Лучше заменить "a or 'Choice %d' % i" на функцию, если вы этого не хотите.

Ключевым моментом является то, что map с аргументом None может использоваться для расширения списка до необходимой длины с None в необходимых местах.

Более аккуратная (более питоническая) версия будет:

def extend_choices(lst,length): def replace_empty(value,index): if value is None: return 'Choice %d' % index return value return [replace_empty(value,index) for value,index in map(None,lst,range(length))]

1 голос
/ 05 февраля 2009
def choice_n(index):
  return "Choice %d" % (index + 1)

def add_choices(lst, length, default=choice_n):
  """
  >>> add_choices(['a', 'b', None, 'c'], 9)
  ['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9']
  """

  for i, v in enumerate(lst):
    if v is None:
      lst[i] = default(i)

  for i in range(len(lst), length):
    lst.append(default(i))

  return lst

if __name__ == "__main__":
  import doctest
  doctest.testmod()
0 голосов
/ 15 мая 2016
>>> my_list=['a','b',None,'c']
>>> map (lambda x,y:x or 'Choice {}'.format(y+1),my_list,range(9))
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9']
0 голосов
/ 15 апреля 2011

Если все в порядке, чтобы заменить любое ложное значение, например, '' или 0

>>> mylist = ['a','b',None,'c']
>>> map(lambda a,b:a or "Choice %s"%b, mylist, range(1,10))
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9']

Если вы действительно можете заменить только None

>>> map(lambda a,b:"Choice %s"%b if a is None else a, mylist, range(1,10))
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9']
0 голосов
/ 10 сентября 2010

Мои два цента ...

def extendchoices(clist):
    clist.extend( [None]*(9-len(clist)) )
    for i in xrange(9):
        if clist[i] is None: clist[i] = "Choice %d"%(i+1) 
0 голосов
/ 05 февраля 2009

Я бы также рекомендовал использовать xrange вместо range. Функция xrange генерирует числа по мере необходимости. Диапазон генерирует их заранее. Для небольших наборов это не имеет большого значения, но для больших диапазонов экономия может быть огромной.

0 голосов
/ 05 февраля 2009
>>> in_list = ["a","b",None,"c"]
>>> new = ['choice ' + str(i + 1) if j is None else j for i, j in enumerate(in_list)]
>>> new.extend(('choice ' +str(i + 1) for i in range(len(new), 9)))
>>> new
['a', 'b', 'choice 3', 'c', 'choice 5', 'choice 6', 'choice 7', 'choice 8', 'choice 9']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...