Python Map 函数数据处理的终极指南

介绍

我们可以使用 Python 内置函数 map() 对可迭代对象(如 列表字典)中的每个项目应用一个函数,并返回一个新的迭代器以获取结果。map() 返回一个映射对象(迭代器),我们可以在程序的其他部分使用它。我们还可以将映射对象传递给 list() 函数或其他序列类型,以创建一个可迭代对象。

map() 函数的语法如下:

map(function, iterable, [iterable 2, iterable 3, ...])

与使用 for 循环 相比,map() 函数提供了一种对可迭代对象中的每个项目应用函数的方法。因此,它通常可以更高效,因为它一次只对一个项目应用函数,而不是将项目复制到另一个可迭代对象中。当处理大型数据集的程序时,这尤其有用。map() 还可以通过一次从每个可迭代对象发送一个项目到函数,来接受多个可迭代对象作为函数的参数。

在本教程中,我们将回顾三种使用 map() 的不同方法:使用 lambda 函数、使用用户定义的函数,最后使用内置函数结合多个可迭代参数。

使用 Lambda 函数

map() 的第一个参数是一个函数,我们用它来应用于每个项目。Python 针对我们传入 map() 的可迭代对象中的每个项目调用一次该函数,并在映射对象中返回处理后的项目。对于第一个函数参数,我们可以传入用户定义的函数,或者在表达式不太复杂时使用 lambda 函数。

使用 lambda 函数的 map() 语法如下:

map(lambda item: item[] expression, iterable)

对于如下列表,我们可以实现一个 lambda 函数,并应用于列表中的每个项目:

numbers = [10, 15, 21, 33, 42, 55]

要对我们的每个数字应用表达式,我们可以使用 map()lambda

mapped_numbers = list(map(lambda x: x * 2 + 3, numbers))

在这里我们将列表中的一个项目声明为 x。然后我们添加我们的表达式。我们将数字列表作为 map() 的可迭代对象传入。

为了立即获得结果,我们打印 map 对象的列表:

print(mapped_numbers)
Output
[23, 33, 45, 69, 87, 113]

我们使用了list(),这样map对象就会以列表的形式返回,而不是像<map object at 0x7fc250003a58>这样不太易读的对象。map对象是我们结果的迭代器,因此我们可以用for循环遍历它,或者使用list()将其转换为列表。我们这样做是因为这是查看结果的好方法。

最终,map()在处理大型数据集时最为有用,因此我们可能会进一步使用map对象,通常不会在它们上使用像list()这样的构造函数。

对于较小的数据集,列表推导可能更合适,但出于本教程的目的,我们使用一个小数据集来演示map()

实现用户定义函数

类似于lambda,我们可以使用自己定义的函数来应用于可迭代对象。当你处理单行表达式时,lambda函数更有用,而当表达式变得复杂时,用户定义函数更合适。此外,当我们需要传递另一块数据给应用于可迭代对象的函数时,用户定义函数在可读性上可能是更好的选择。

例如,在以下可迭代对象中,每个项都是一个字典,包含有关我们每个水族馆生物的不同细节:

aquarium_creatures = [
 {"name": "sammy", "species": "shark", "tank number": 11, "type": "fish"},
 {"name": "ashley", "species": "crab", "tank number": 25, "type": "shellfish"},
 {"name": "jo", "species": "guppy", "tank number": 18, "type": "fish"},
 {"name": "jackie", "species": "lobster", "tank number": 21, "type": "shellfish"},
 {"name": "charlie", "species": "clownfish", "tank number": 12, "type": "fish"},
 {"name": "olly", "species": "green turtle", "tank number": 34, "type": "turtle"}
]

我们决定将所有水族馆生物实际上移入同一个水箱。我们需要更新记录以反映所有生物都移入水箱42。为了让map()访问每个字典和字典中的每个键值对,我们构造了一个嵌套函数:

def assign_to_tank(aquarium_creatures, new_tank_number):
 def apply(x):
  x["tank number"] = new_tank_number
  return x
 return map(apply, aquarium_creatures)

我们定义了一个assign_to_tank()函数,该函数接受new_tank_number作为参数。在assign_to_tank()中,我们在最后一行将apply()作为map()的函数。assign_to_tank函数将返回map()生成的迭代器。

apply()接受x作为参数,它表示我们列表中的一个项目 – 一个单独的字典。

接下来我们定义x是从中的"tank number"键,并且应该存储传入的new_tank_number。我们在应用新水箱号后返回每个项目。

我们使用包含我们字典列表和我们想要为每个生物替换的新水箱号的assign_to_tank()进行调用:

assigned_tanks = assign_to_tank(aquarium_creatures, 42)

一旦函数完成,我们将我们的map对象存储在assigned_tanks变量中,然后将其转换为列表并打印:

print(list(assigned_tanks))

从这个程序中,我们将收到以下输出:

Output
[{'name': 'sammy', 'species': 'shark', 'tank number': 42, 'type': 'fish'}, {'name': 'ashley', 'species': 'crab', 'tank number': 42, 'type': 'shellfish'}, {'name': 'jo', 'species': 'guppy', 'tank number': 42, 'type': 'fish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': 42, 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': 42, 'type': 'fish'}, {'name': 'olly', 'species': 'green turtle', 'tank number': 42, 'type': 'turtle'}]

我们已经将新水箱号映射到我们的字典列表中。使用我们定义的函数,我们可以将map()有效地应用于列表中的每个项目。

使用内置函数与多个可迭代对象

lambda函数或我们自己定义的函数一样,我们可以将Python内置函数与map()一起使用。要对多个可迭代对象应用一个函数,我们在第一个可迭代对象后面传入另一个可迭代对象名称。例如,使用pow()函数,它接受两个数字以计算基数的幂值。

这里是我们希望与pow()一起使用的整数列表:

base_numbers = [2, 4, 6, 8, 10]
powers = [1, 2, 3, 4, 5]

接下来,我们将pow()作为我们的函数传入map(),并提供这两个列表作为我们的可迭代对象:

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

map()将对每个列表中相同的项应用pow()函数以提供幂值。因此,我们的结果将显示2**14**26**3,等等:

Output
[2, 16, 216, 4096, 100000]

如果我们向map()提供一个比另一个长的可迭代对象,map()将在达到最短可迭代对象的末尾时停止计算。在以下程序中,我们将base_numbers扩展为三个额外的数字:

base_numbers = [2, 4, 6, 8, 10, 12, 14, 16]
powers = [1, 2, 3, 4, 5]

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

因此,这个程序的计算将不会改变,因此它仍然会产生相同的结果:

Output
[2, 16, 216, 4096, 100000]

我们使用了 map() 函数与 Python 内置函数,并且已经看到它可以处理多个可迭代对象。我们还回顾了 map() 将继续处理多个可迭代对象,直到到达项目最少的可迭代对象的末尾。

结论

在本教程中,我们探讨了在 Python 中使用 map() 函数的各种方法。您现在可以使用 map() 与自定义函数、lambda 表达式以及其他内置函数。此外,map() 可以应用于需要多个可迭代对象的函数,增强了其在数据处理任务中的灵活性。

出于演示目的,我们将 map() 的结果直接转换为列表。在实际应用中,返回的 map 对象可以进一步处理以满足特定需求。

为了加深您对 Python 的理解,请使用以下资源:

这些资源将为您提供对Python功能的全面理解,以及如何在项目中有效利用它们。

如果您想了解更多关于Python的内容,请查看我们的如何在Python中编程系列以及我们的Python主题页面。要了解有关在函数式编程中处理数据集的更多信息,请查看我们的关于filter()函数的文章。

常见问题

Python中的map()函数有什么作用?

在Python中,map()函数接受一个函数和一个或多个可迭代对象,并返回一个迭代器,该迭代器将给定函数应用于提供的可迭代对象的每个元素。换句话说,它“映射”该函数到可迭代对象中的每个项目。例如:

numbers = [1, 2, 3, 4]
squares = map(lambda x: x**2, numbers)

这里,squares将是一个迭代器,包含1, 4, 9, 16.

如何在Python中创建一个映射?

您可以通过调用内置的map()函数,传入一个函数和至少一个可迭代对象作为参数来创建一个映射对象。例如:

def add_one(x):
    return x + 1

my_list = [1, 2, 3]
mapped = map(add_one, my_list)  # 创建一个映射对象

然后,您可以遍历映射对象或将其转换为列表以查看结果:

print(list(mapped))  # [2, 3, 4]

在Python中,映射是懒加载的吗?

是的,在Python 3中,map()返回一个懒迭代器,这意味着它不会一次性处理或存储所有结果。相反,它会在您遍历时按需计算每个结果。这在处理大数据集时可以更加节省内存,但也意味着您不能直接索引或重复遍历同一个映射对象,而不重新构建它。

如何使用 map() 函数?

map() 函数的工作原理如下:

  1. 你提供一个函数和一个或多个可迭代对象。
  2. map() 从每个可迭代对象中检索一个元素。
  3. 它将这些元素作为参数调用该函数。
  4. 它返回该函数调用的结果。
  5. 它重复这个过程,直到任一可迭代对象耗尽。

如果给定多个可迭代对象,map() 会在最短的可迭代对象耗尽时停止。例如:

numbers = [1, 2, 3]
others = [10, 20, 30]
result = map(lambda x, y: x + y, numbers, others)
print(list(result))  # [11, 22, 33]

我应该在 Python 中使用 map 吗?

是否应该使用 map() 取决于个人偏好和可读性:

优点:

  • 在某些情况下可以更简洁。
  • 在某些场景下,它可能比列表推导稍微快一点(尽管通常没有显著差异)。

缺点:

  • 使用列表推导或生成器表达式的代码通常被认为更“Pythonic”,更易于阅读。
  • 较新的 Python 程序员可能会发现列表推导更直观。

简而言之,如果使用 map() 可以使您的代码更清晰、更直接,则应使用它。否则,列表推导或生成器表达式是一个非常常见的替代方案。

如何在 Python 中将 map 转换为字符串?

map 对象是一个迭代器,而不是字符串。如果您想将 map() 调用的结果转换为字符串,您首先需要对其进行迭代。常见的方法包括:

  • 转换为列表然后再转换为字符串表示:
mapped = map(str, [1, 2, 3])
string_representation = str(list(mapped))  # "[‘1’, ‘2’, ‘3’]"
  • 如果结果是字符串元素,则连接结果:
mapped = map(str, [1, 2, 3])
joined_string = ''.join(mapped)  # "123"

最佳方法取决于您是希望获得人类可读的列表表示(str(list(...)))还是结果的连接(''.join(...))。

map count() 的作用是什么?

Python中的map对象没有内置的count()方法。 count()方法适用于列表、字符串和某些其他集合。如果您想要计算map对象生成的值的出现次数,必须先将其转换为列表(这会消耗迭代器):

mapped = map(lambda x: x*2, [1, 2, 3, 2])
mapped_list = list(mapped)
count_of_4 = mapped_list.count(4)  # 2,因为2*2=4出现了两次

如果您不想转换为列表就需要计数,可以手动进行迭代:

count_of_value = sum(1 for x in map(lambda x: x*2, [1, 2, 3, 2]) if x == 4)

mapfilter在Python中的作用是什么?

  • map(function, iterable):将函数应用于可迭代对象的每个元素,并返回结果的迭代器。

  • filter(function, iterable):返回一个迭代器,其中包含满足条件function(element)为True的可迭代对象的元素。如果function为None,则返回本身为真值的元素。

例如:

nums = [1, 2, 3, 4, 5]
mapped_nums = map(lambda x: x*2, nums)        # [2, 4, 6, 8, 10]
filtered_nums = filter(lambda x: x > 2, nums) # [3, 4, 5]

map 转换每个元素,而 filter 根据条件选择某些元素。

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-python-map-function