Список карт на словарь

Есть ли способ сопоставить список со словарем? То, что я хочу сделать, это дать ему функцию, которая вернет имя ключа, а значение будет исходным. Например:

somefunction(lambda a: a[0], ["hello", "world"])
=> {"h":"hello", "w":"world"}

(Это не конкретный пример, который я хочу сделать, я хочу, чтобы такая общая функция, как map(), могла это сделать)

Ответы

Ответ 1

Я не думаю, что существует стандартная функция, которая делает именно это, но ее очень легко построить с помощью встроенного dict и понимания:

def somefunction(keyFunction, values):
    return dict((keyFunction(v), v) for v in values)

print somefunction(lambda a: a[0], ["hello", "world"])

Вывод:

{'h': 'hello', 'w': 'world'}

Но придумать хорошее имя для этой функции сложнее, чем реализовать ее. Я оставлю это как упражнение для читателя.

Ответ 2

В Python 3 вы можете использовать синтаксис понимания этого словаря:

def foo(somelist):
    return {x[0]:x for x in somelist}

Ответ 3

Если я правильно понимаю ваш вопрос, я считаю, что вы можете выполнить это с помощью комбинации map, zip и конструктора dict:

def dictMap(f, xs) :
    return dict(zip(map(f, xs), xs)

И более удачная реализация:

def dictMap(f, xs) :
    return dict((f(i), i) for i in xs)

Ответ 4

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

Параметризация этих результатов в более сложной, но очень общей функции. Вот тот, который я использовал в течение нескольких лет:

def reduce_list(key, update_value, default_value, l):
    """Reduce a list to a dict.

    key :: list_item -> dict_key
    update_value :: key * existing_value -> updated_value
    default_value :: initial value passed to update_value
    l :: The list 

    default_value comes before l. This is different from functools.reduce, 
    because functools.reduce order is wrong.
    """
    d = {}
    for k in l:
        j = key(k)
        d[j] = update_value(k, d.get(j, default_value))
    return d

Затем вы можете написать свою функцию, сказав:

reduce_list(lambda s:s, lambda s,old:s[0], '', ['hello', 'world'])
# OR
reduce_list(lambda s:s, lambda s,old: old or s[0], '', ['hello', 'world'])

В зависимости от того, хотите ли вы сохранить первое или последнее слово, начиная с, например, "h".

Эта функция очень общая, однако, поэтому большую часть времени она является основой для других функций, таких как group_dict или histogram:

def group_dict(l):
    return reduce_list(lambda x:x, lambda x,old: [x] + old, [], l)
def histogram(l):
    return reduce_list(lambda x:x, lambda x,total: total + 1, 0, l)

Ответ 5

>>> dict((a[0], a) for a in "hello world".split())
{'h': 'hello', 'w': 'world'}

Если вы хотите использовать функцию вместо подписи, используйте operator.itemgetter:

>>> from operator import itemgetter
>>> first = itemgetter(0)
>>> dict((first(x), x) for x in "hello world".split())
{'h': 'hello', 'w': 'world'}

Или как функция:

>>> dpair = lambda x : (first(x), x)
>>> dict(dpair(x) for x in "hello world".split())
{'h': 'hello', 'w': 'world'}

Наконец, если вы хотите, чтобы более чем одно слово на письмо было возможно, используйте collections.defaultdict

>>> from collections import defaultdict
>>> words = defaultdict(set)
>>> addword = lambda x : words[first(x)].add(x)
>>> for word in "hello house home hum world wry wraught".split():
        addword(word)


>>> print words['h']
set(['house', 'hello', 'hum', 'home'])

Ответ 6

Взяв подсказки из других ответов, я достиг этого с помощью операции с картами. Я не уверен, что это точно отвечает на ваш вопрос.

mylist = ["hello", "world"]
def convert_to_dict( somelist ):
    return dict( map( lambda x: (x[0], x), somelist ) )

final_ans = convert_to_dict( mylist ) 
print final_ans