функция map и filter для массива списков - PullRequest
0 голосов
/ 27 ноября 2018

Я хочу отобразить массив списков, подобный приведенному ниже, используя функцию process_slide_index(x)

tile_index:

[(1, 1024, 0, 16, 0, 0), (1, 1024, 0, 16, 0, 1), (1, 1024, 0, 16, 0, 2), (1, 1024, 0, 16, 0, 3), (1, 1024, 0, 16, 0, 4), (1, 1024, 0, 16, 0, 5), (1, 1024, 0, 16, 0, 6),...]

плитки:

tiles = map(lambda x: process_slide_index(x), tiles_index)

функция карты:

def process_slide_index(tile_index):
    print("PROCESS SLIDE INDEX")
    slide_num, tile_size, overlap, zoom_level, col, row = tile_index
    slide = open_slide(slide_num)
    generator = create_tile_generator(slide, tile_size, overlap)
    tile = np.asarray(generator.get_tile(zoom_level, (col, row)))

    return (slide_num, tile)

Я применяю функцию карты, но, похоже, я не попал внутрь моего process_slide_index(tile_index)функция.

Я также хочу отфильтровать некоторые результаты, учитывая функцию, которая возвращает True из False.Но еще раз моя функция не достигает функции фильтра.

filtered_tiles = filter(lambda x: keep_tile(x, tile_size, tissue_threshold), tiles)

Что я делаю не так?

С уважением

РЕДАКТИРОВАТЬ Единственный способЯ получил сообщение о том, что контрольная точка PROCESS SLIDE INDEX добавляла list(map(print, tiles)) после строки плитки .Я использовал это, чтобы попытаться отладить, и мои отпечатки начали появляться.Я сейчас в замешательстве.

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

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

tiles = map(process_slide_index, tiles_index)
0 голосов
/ 27 ноября 2018

TL; DR -

  • Понимание списка может сделать много вещей, которые вы могли бы хотеть здесь.[x for x in mylist if x > y] - это мощное выражение, которое более чем заменяет filter().Это также хорошая альтернатива map(), и она намного более эффективна, чем использование лямбда-выражения.Он также выдает список вместо генератора, что, вероятно, предпочтительнее в вашем случае.(Если вы имеете дело с огромными потоками данных, вы можете использовать map и filter, потому что с генераторами вам не нужно хранить все это в оперативной памяти, вы можетевычисляйте по одному значению за раз.) Если вам нравится это предложение и вы хотите пропустить разговор, я дам вам код в 2b .

  • Ненаписать лямбда-выражение для функции, которая уже существует!Лямбда-выражения - это встроенные функции, в которых вы их не определили.Они намного медленнее и ведут себя странно.Избегайте их, где это возможно.Вы можете заменить лямбду в вашем map() вызове самой функцией: tiles = map(process_slide_index, tiles_index)

Длинная версия:

Есть две проблемы, обе довольно легко исправить.Во-первых, это скорее вопрос стиля / эффективности, но он также избавит вас от некоторых непонятных головных болей:

1. Вместо создания лямбда-выражения лучше использовать функциюВы уже пошли на работу по определению!tiles = map(process_slide_index, tiles_index) отлично справляется с работой и ведет себя лучше.

2. Вероятно, вам следует перейти к списку пониманий.Зачем?Потому что map() и filter() более уродливы и медленнее, если вам нужно использовать лямбду или потом преобразовать вывод в список.Тем не менее, если вы настаиваете на использовании map() и filter() ...

2a. Когда вам нужно передать несколько аргументов в функцию для map, попробуйте functools.partial, если вызнать многие ценности заранее.Я думаю, что это ошибка в вашей логике, когда вы пытаетесь
filtered_tiles = filter(lambda x: keep_tile(x, tile_size, tissue_threshold), tiles)
То, что вы говорите, это сделать, это вызвать keep_tile() для вектора [x for x in tiles], удерживая tile_size и tissue_threshold константа.

Если это предполагаемое поведение, попробуйте import functools и используйте functools.partial(keep_tile, tile_size, tissue_threshold).
Примечание: использование functools.partial требует, чтобы любые переменные, которые вы передаете частичной функции, были самыми правыми аргументами, поэтому вы 'пришлось переписать заголовок функции как def keep_tile(tile_size, tissue_threshold, tiles): вместо def keep_tile(tiles, tile_size, tissue_threshold):.(Смотрите, нам снова удается избежать лямбда-выражения!)

Если это не предполагаемое поведение, и вы хотите, чтобы каждое из этих значений изменялось при каждом вызове, просто передайтекортеж в!filter(keep_tile, (tile, tile_size, tissue_threshold))).Если вы просто хотите получить переменную tile из этого, вы можете использовать понимание списка:
[x[0] for x in filter(keep_tile, (tile, tile_size, tissue_threshold)))] (Опять же, без лямбд.) Однако, так как мы здесь уже делаем понимание списка, вы можете захотетьпопробуйте решение в 2b.

2b. В более поздних выпусках Python это, как правило, быстрее и чище, просто для использования понимания списка, такого как [x[0] for x in tiles if keep_tile(*x)].(Или, если вы хотите сохранить два других значения постоянными, вы можете использовать [x for x in tiles if keep_tile(x, tile_size, tissue_threshold)].) Каждый раз, когда вы просто собираетесь прочитать вывод map() или filter() в список впоследствии, вам, вероятно, следуетвместо этого использовали понимание списка.На данный момент map() и filter() действительно полезны только для потоковой передачи результатов по конвейеру или для асинхронных подпрограмм.

0 голосов
/ 27 ноября 2018

Вы используете python3, в python2 map и filter возвращаете список, но в python3 они возвращают объект, который вы должны использовать, чтобы получитьзначения:

>>> l = list(range(10))
>>> def foo(x):
...     print(x)
...     return x+1
... 
>>> map(foo, l)
<map object at 0x7f69728da828>

Для использования этого объекта вы можете использовать list, например.Обратите внимание, как print называется в этот раз:

>>> list(map(foo, l))
0
1
2
3
4
5
6
7
8
9
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Эти объекты ленивы, это означает, что они yield значения по одному.Проверьте различия при использовании их в качестве итераторов в цикле for:

>>> for e in map(foo, l):
...     print(e)
... 
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10

Использование list делает то же самое, но сохраняет каждое принятое значение в этом списке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...