2014-09-17 4 views
1

Как я могу заставить эту функцию работать правильно независимо от итерации аргумента X и без каких-либо условий if/else?Обработка итерационных и неистребимых объектов.

Я бы предположил, что этот вопрос задавали/отвечали раньше, но я ничего не мог найти.

def do_something(X): 
    return map(lambda x: x ,X) 

# Possible input: 

do_something([1,2,3]) #-> [1,2,3] 
do_something(1) # -> [1] 

РЕДАКТИРОВАТЬ:

Я ожидаю скалярная аргумент, который будет рассматриваться как 1D, один элемент массива, например, 1 -> [1], поэтому возвращаемое значение всегда должно быть списком.

Numpy Решение:

Просто понял, что NumPy обеспечивает эту функциональность:

import numpy 

def do_something(X): 
    return map(lambda x: x ,numpy.atleast_1d(X)) 

Так что теперь вопрос: "Есть ли способ добиться того же без импорта NumPy"?

+0

Что вы ожидаете, произойдет в каждом случае? Если вторая версия возвращает обработанный элемент напрямую или список из одного элемента, например? Я предполагаю, что вы планируете что-то другое, кроме NOOP, которое вы сейчас используете? – jonrsharpe

+0

Я добавил ответ на исходный вопрос – memecs

+3

, если вы имеете дело со строками. они тоже повторяются (даже строки из 1 символа) – wim

ответ

2

EAFP.

def do_something(X): 
    try: 
     return map(lambda x: x, X) 
    except TypeError: 
     return map(lambda x: x, [X]) 

В принципе, вы пытаетесь map с данным X, и если это не удается, попробуйте еще раз со списком одноэлементной содержащего X. Обратите внимание: если ваша функция может поднять TypeError, вам необходимо как-то проверить, возникает ли ошибка, вызванная map, или функцией, которую она вызывает. Это возможно ... с оператором if.

+0

no 'return' в лямбда – wim

+0

Я отредактирую его! :-) – mgilson

+0

Ты был слишком быстр для меня. (Я просто скопировал и вставил исходный код ...) – kindall

1

Вы можете проверить, является ли итератор или не пройденные предметы, основываясь на том, что вы можете справиться с этим:

>>> from collections import Iterable 
def do_something(X): 
    f = lambda x: x**2 
    if isinstance(X, Iterable): 
     return map(f, X) 
    return f(X) 
>>> do_something([1, 2, 3, 4]) 
[1, 4, 9, 16] 
>>> do_something(2) 
4 
>>> do_something(iter(range(3, 7))) 
[9, 16, 25, 36] 

Если вы хотите, чтобы вернуться [4] во втором случае, то вам необходимо изменить его:

def do_something(X): 
    return map(lambda x: x**2, X if isinstance(X, Iterable) else [X]) 
+0

Нет, если-else i.e нет проверки типа;) – memecs

+1

@memecs почему бы и нет? Если это условия, налагаемые как часть вашей домашней работы, разве вы не должны делать это сами? – jonrsharpe

+0

@jonrsharpe Почему это должно быть домашнее задание? Я задал простой вопрос с уловкой: no if-else. Зачем? Потому что это дополнительные строки, которые я не хочу печатать. Делает код менее элегантным. Из текущих ответов я понимаю, что нет никакого тривиального решения (например, itertools, предоставляющего некоторые специальные функции) – memecs

1

Я советую прятать вещи вы не хотите видеть в вспомогательной функции:

from collections import Iterable 

def make_sure_iterable(X): 
    return X if isinstance(X, Iterable) and not isinstance(X, basestring) else [X] 

Затем, когда вы используете аргумент, оберните его вызовом вспомогательной функции:

def do_something(X): 
    return map(lambda x: x, make_sure_iterable(X)) 
+0

Да, это, наверное, лучший вариант. Кажется, полезная функция, хотя она доступна в itertools. – memecs

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