如何在python中减少元组列表
我有一个数组,我想计算数组中每个项目的出现次数 我已经设法使用map函数来生成元组列表如何在python中减少元组列表,python,python-2.7,mapreduce,Python,Python 2.7,Mapreduce,我有一个数组,我想计算数组中每个项目的出现次数 我已经设法使用map函数来生成元组列表 def mapper(a): return (a, 1) r = list(map(lambda a: mapper(a), arr)); //output example: //(11817685, 1), (2014036792, 1), (2014047115, 1), (11817685, 1) 我希望reduce函数可以帮助我按照每个元组中的第一个数字(id)对计数进行分组。例如:
def mapper(a):
return (a, 1)
r = list(map(lambda a: mapper(a), arr));
//output example:
//(11817685, 1), (2014036792, 1), (2014047115, 1), (11817685, 1)
我希望reduce函数可以帮助我按照每个元组中的第一个数字(id)对计数进行分组。例如:
(11817685, 2), (2014036792, 1), (2014047115, 1)
我试过了
cnt = reduce(lambda a, b: a + b, r);
还有其他一些方法,但它们都不起作用
注意
感谢所有关于解决问题的其他方法的建议,但我只是在这里学习Python和如何实现map reduce,我已经简化了我的实际业务问题,使其易于理解,因此请向我展示一种正确的map reduce方法 您可以使用
计数器:
from collections import Counter
arr = [11817685, 2014036792, 2014047115, 11817685]
counter = Counter(arr)
print zip(counter.keys(), counter.values())
编辑:
正如@ShadowRanger计数器所指出的那样,计数器具有项()
方法:
from collections import Counter
arr = [11817685, 2014036792, 2014047115, 11817685]
print Counter(arr).items()
如果您只需要cnt
,那么dict
可能比元组的列表
更好(如果您需要这种格式,只需使用dict.items
)
collections
模块为此提供了一个有用的数据结构,即defaultdict
from collections import defaultdict
cnt = defaultdict(int) # create a default dict where the default value is
# the result of calling int
for key in arr:
cnt[key] += 1 # if key is not in cnt, it will put in the default
# cnt_list = list(cnt.items())
不使用任何外部模块,您可以使用一些逻辑,不使用任何模块:
track={}
if intr not in track:
track[intr]=1
else:
track[intr]+=1
示例代码:
对于这些类型的列表问题,有一种模式:
因此,假设您有一个列表:
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
您希望将其转换为dict,作为元组的第一个元素,作为键,作为元组的第二个元素。比如:
{2008: [9], 2006: [5], 2007: [4]}
但有一个陷阱,您也希望那些具有不同值但键相同的键,如(2006,1)和(2006,5)键相同但值不同。您希望这些值仅附加一个键,以便获得预期的输出:
{2008: [9], 2006: [1, 5], 2007: [4]}
对于这类问题,我们采取如下措施:
首先创建一个新的dict,然后我们遵循以下模式:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
因此,我们首先检查key是否在new dict中,如果它已经存在,则将duplicate key的值添加到其值中:
完整代码:
a=[(2006,1),(2007,4),(2008,9),(2006,5)]
new_dict={}
for item in a:
if item[0] not in new_dict:
new_dict[item[0]]=[item[1]]
else:
new_dict[item[0]].append(item[1])
print(new_dict)
输出:
{2008: [9], 2006: [1, 5], 2007: [4]}
写信给之后,我想起了这篇文章,并认为在这里写一个类似的答案会有所帮助
下面是一种在列表中使用reduce
以获得所需输出的方法
arr = [11817685, 2014036792, 2014047115, 11817685]
def mapper(a):
return (a, 1)
def reducer(x, y):
if isinstance(x, dict):
ykey, yval = y
if ykey not in x:
x[ykey] = yval
else:
x[ykey] += yval
return x
else:
xkey, xval = x
ykey, yval = y
a = {xkey: xval}
if ykey in a:
a[ykey] += yval
else:
a[ykey] = yval
return a
mapred = reduce(reducer, map(mapper, arr))
print mapred.items()
其中打印:
[(2014036792, 1), (2014047115, 1), (11817685, 2)]
有关更详细的说明,请参见。lambda:mapper(a)
?为什么不直接通过mapper
?另外:您的预期输出是什么?谢谢您的评论。是的,我可以直接通过mapper,我正在试验其他东西。已添加我的预期输出。您需要r
还是它只是一个中介?只是一个中介。无论reduce
还是map
都不能真正帮助您。这类任务就是存在collections.Counter
的原因(对于输入已经排序的更特殊的情况,itertools.groupby
)。Map/Reduce策略适用于多个映射器并行输入多个还原器的情况;盲目地将相同的模式应用于纯单线程代码是浪费的(在Map/Reduce情况下也是浪费的,你只需要依靠荒谬的并行级别来弥补开销)。为什么zip
键和值?有一种直接执行此操作的items
方法:print counter.items()
,还有一种特殊用途的方法most\u common
,它按频率顺序显示结果(对结果数量有可选限制),例如print counter.most\u common()
。