GVKun编程网logo

有没有任何pythonic方法可以组合两个dicts(为两者中出现的键添加值)?

9

如果您想了解有没有任何pythonic方法可以组合两个dicts的相关知识,那么本文是一篇不可错过的文章,我们将对为两者中出现的键添加值?进行全面详尽的解释,并且为您提供关于EffectivePyth

如果您想了解有没有任何pythonic方法可以组合两个dicts的相关知识,那么本文是一篇不可错过的文章,我们将对为两者中出现的键添加值?进行全面详尽的解释,并且为您提供关于Effective Python - 用pythonic方式思考、ios – Swift:如何组合两个Dictionary实例?、python – 在collections.defaultdict中禁止键添加、python – 将dict的键和值从str转换为Unicode的最快方法?的有价值的信息。

本文目录一览:

有没有任何pythonic方法可以组合两个dicts(为两者中出现的键添加值)?

有没有任何pythonic方法可以组合两个dicts(为两者中出现的键添加值)?

例如我有两个字典:

Dict A: {''a'': 1, ''b'': 2, ''c'': 3}Dict B: {''b'': 3, ''c'': 4, ''d'': 5}

我需要一种“组合”两个字典的pythonic方式,结果是:

{''a'': 1, ''b'': 5, ''c'': 7, ''d'': 5}

也就是说:如果一个键出现在两个dict中,则添加它们的值,如果它只出现在一个dict中,则保留其值。

答案1

小编典典

使用collections.Counter

>>> from collections import Counter>>> A = Counter({''a'':1, ''b'':2, ''c'':3})>>> B = Counter({''b'':3, ''c'':4, ''d'':5})>>> A + BCounter({''c'': 7, ''b'': 5, ''d'': 5, ''a'': 1})

Counters 基本上是 的子类dict,因此您仍然可以使用它们执行通常使用该类型执行的所有其他操作,例如迭代它们的键和值。

Effective Python - 用pythonic方式思考

Effective Python - 用pythonic方式思考

Effective Python

1.确认自己所用的Python版本

优先使用python3,抛弃python2

查看python版本信息: python --version

 

2.遵循PEP8风格指南

采用一致的编码风格令代码更加易读,利于多人协作

绝对应该遵守的规则

 

空格

(1)使用space来表示缩进,而不要使用tab

(2)和语法相关的每一层缩进都用4个空格来表示

(3)每行的字符不应超过79

(4)对于多行长表达式,除了首行之外的其余各行都应该在通常的缩进级别之上再加4个空格

(5)文件中的函数与类之间应该用两个空行隔开

(6)同一个类中的两个方法之间应该用一个空行隔开

(7)在使用下标获取列表元素、调用函数或给关键字参数赋值时,不要在两旁添加空格

(8)为变量赋值时,赋值符号两边各添加一个空格

 

命名

(1)函数、变量及属性应该用小写字母来拼写,各单词间用下划线连接,如bub_sort

(2)受保护的实例属性,应以单下划线开头,如_name

(3)私有的实例属性,应以双下划线开头,如__name

(4)类与异常,应以每个单词首字母大写的形式命名,如Note

(5)模块级别的常量,应全部采用大写字母拼写,单词之间用下划线连接,如ERR_CODE

(6)类中实例方法的首个参数,应该命名为self,表示该对象自身

(7)类方法的首个参数,应该命名为cls,表示该类自身

 

表达式和语句

(1)采用内联形式的否定词,不要把否定词放在整个表达式的前面,例如应该是 if a is not b 而不是if not a is b

(2)不要通过检测长度的办法,如len(list1) == 0来判断list1是否为[]或“”等空值,而是采用if not list1来判断,它会假定空值将自动评估为False

(3)检测list1是否为[1]或‘hi’等非空值,应用if list1语句会默认把非空的值判断为True

(4)不要编写单行的if语句、for循环、while循环及except复合语句,而是应该把这些语句分成多行来书写,以示清晰

(5)import语句应该总是放在文件开头

(6)引入模块的时候,总是应该使用绝对的名称,而不应该根据当前模块的路径来使用相对名称

  例如,引入bar包中的foo模块时,应该完整的写出from bar import foo,而不应该写import foo

(7)如果一定要用相对名称来编写import语句,应该采用明确的写法:from .import foo

(8)文件中的import语句应该按顺序划分成三个部分,分别表示标准模块、第三方模块以及自用模块。

  在每一个部分中,各import''语句应该按模块的顺序来排列

 

5.了解切割序列的办法

(1)不要写多余的代码;当从索引开头获取元素,应把起始索引留空;当一直取到索引末尾,应把终止索引留空。

nums = [0, 1, 2, 3, 4, 5]
res1 = nums[:] #[0, 1, 2, 3, 4, 5]
res2 = nums[:3] #[0, 1, 2]
res3 = nums[3:] #[3, 4, 5]
res4 = nums[1:3] #[1, 2]
res5 = nums[2:-1] #[2, 3, 4]
res6 = nums[:-1] #[0, 1, 2, 3, 4]
res7 = nums[-2:] #[4, 5]
res8 = nums[-3:-1] #[3, 4]

 

(2)切片操作不计较开始索引和结束索引是否越界。

 利用这一特性,我们可以限定输入序列的最大长度

nums = [_ for _ in range(30)]
first_ten_items = nums[:10]
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
last_ten_items = nums[-10:]
#[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

 

(3)对列表赋值时,如果使用切片操作,会把原列表中在相关范围内的值替换成新值,

位于切片之前和之后的值不变,列表会根据新值的个数相应的扩张和收缩。

nums = [0, 1, 2, 3, 4, 5]
nums_temp = nums
nums[:3] = [''a'']
print(nums, nums is nums_temp) #[''a'', 3, 4, 5] True

 

来看个特殊的

nums = [0, 1, 2, 3, 4, 5]
nums_temp = nums
nums[:] = [''a'', ''b'', ''c'']
print(nums, nums is nums_temp) #[''a'', ''b'', ''c''] True

说明:把右侧的新值赋值一份去替换左侧列表的全部元素,但不会重新分配新的列表,这个从nums is nums_temp为True可知。

 

8.不要使用包含两个以上表达式的列表推导

列表支持多级循环,每一级循环也支持多项条件

超过两个表达式的 列表推导不易理解,应尽量避免

 

栗子1,遍历二维数组

1 list1 = [[1, 2], [3, 4], [5, 6]]
2 res1 = [x for row in list1 for x in row]
3 print(res1) #[1, 2, 3, 4, 5, 6]

 

栗子2,一维列表多条件

1 list2 = [1, 2, 3, 4, 5, 6]
2 res2 = [y for y in list2 if y > 4 and y % 2 == 0]
3 print(res2) #[6]

 

栗子3,根据二维数组来创建一个新的二维数组

1 list3 = [[1, 2], [3, 4]]
2 squares = [[x**2 for x in row] for row in list3]
3 print(squares)  #[[1, 4], [9, 16]]

 

10.尽量用enumerate取代range

1)range常用在一系列整数上的迭代

1 for i in range(10):
2     print(i)
View Code

 

2)对于字符串列表,可直接使用for...in迭代

1 fruits = ["apple", "banana", "pear"]
2 for ele in fruits:
3     print(ele)
View Code

 

3)对于迭代列表时,需要知道当前元素的索引

方式一:range

1 fruits = ["apple", "banana", "pear"]
2 for i in range(len(fruits)):
3     print("%d: %s" % (i, fruits[i]))
View Code

说明:代码有些生硬,必须先获得序列的长度,再通过下标访问元素,代码难免有些臃肿

 

方式二:enumerate

1 fruits = ["apple", "banana", "pear"]
2 for i, ele in enumerate(fruits):
3     print("%d: %s" % (i, ele))
View Code

 

要点

1.再需要用到所遍历序列的索引时,一般用enumerate遍历

2.enumerate可指定开始计数的索引

 

11.用zip函数同时遍历两个迭代器

栗子:平行的迭代两个长度相等的列表,并求fruits中长度最长的元素

fruits = ["apple", "banana", "pear"]
letters = [len(fruit) for fruit in fruits]

 

方式一:通过某个列表的长度来执行循环

 1 fruits = ["apple", "banana", "pear"]
 2 letters = [len(fruit) for fruit in fruits]
 3 
 4 longest_name = None
 5 max_letters = 0
 6 
 7 for i in range(len(fruits)):
 8     if letters[i] > max_letters:
 9         max_letters = letters[i]
10         longest_name = fruits[i]
11 
12 print(max_letters)
13 print(longest_name)
View Code

 

方式二:通过enumerate来执行循环

 1 fruits = ["apple", "banana", "pear"]
 2 letters = [len(fruit) for fruit in fruits]
 3 
 4 longest_name = None
 5 max_letters = 0
 6 
 7 for i, fruit in enumerate(fruits):
 8     if letters[i] > max_letters:
 9         max_letters = letters[i]
10         longest_name = fruit
11 
12 print(max_letters)
13 print(longest_name)
View Code

 

方式三:用zip函数来执行循环

 1 fruits = ["apple", "banana", "pear"]
 2 letters = [len(fruit) for fruit in fruits]
 3 
 4 longest_name = None
 5 max_letters = 0
 6 
 7 for fruit, length in zip(fruits, letters):
 8     if length > max_letters:
 9         max_letters = length
10         longest_name = fruit
11 
12 print(max_letters)
13 print(longest_name)
View Code

 

zip工作原理

从每个迭代器中获取该迭代器的下一个元素,并将这些值汇聚成元祖,

zip中受封装的迭代器一般长度都相等,只要有一个耗尽,zip就不会再产生

元祖,所以zip中的迭代器一般长度都相等

 

要点

1.zip函数可以平行遍历多个迭代器

2.python3中的zip相等于生成器,会在遍历过程中逐次产生元祖

3.如果zip中提供的迭代长度不等,那么zip会自动提前终止

4.itertools内置模块中的zip_longest函数可以平行迭代多个迭代器,而不用在乎它们的长度是否相等

 

12.不要在for和while循环后写else代码块

原因

会令代码的可读性降低,不利于维护

要点

当整个循环主体都没遇到break语句时,循环后面的else代码块才会执行

ios – Swift:如何组合两个Dictionary实例?

ios – Swift:如何组合两个Dictionary实例?

如何使用Swift将[Dictionary]添加到另一个[Dictionary]?

我正在使用AlamoFire库将JSON发送到REST服务器。

词典1

let dict1: [String: AnyObject] = [
            kFacebook: [
                kToken: token
            ]
        ]

词典2

let dict2: [String: AnyObject] = [
        kRequest: [
            kTargetUserId: userId
        ]
    ]

如何结合两个字典来实现如下?

let parameters: [String: AnyObject] = [
        kFacebook: [
            kToken: token
        ],kRequest: [
            kTargetUserId: userId
        ]
    ]

我已经尝试了dict1 = dict2但是有一个编译错误。

提前致谢!

解决方法

var d1 = ["a": "b"]
var d2 = ["c": "e"]

extension Dictionary {
    mutating func merge(dict: [Key: Value]){
        for (k,v) in dict {
            updateValue(v,forKey: k)
        }
    }
}

d1.merge(d2)

参考美元& Cent项目
https://github.com/ankurp/Cent/blob/master/Sources/Dictionary.swift

python – 在collections.defaultdict中禁止键添加

python – 在collections.defaultdict中禁止键添加

当在defaultdict对象中查询缺少的键时,该键会自动添加到字典中:

from collections import defaultdict

d = defaultdict(int)
res = d[5]

print(d)
# defaultdict(<class ''int''>,{5: 0})
# we want this dictionary to remain empty

但是,我们通常只想在显式或隐式分配密钥时添加密钥:

d[8] = 1  # we want this key added
d[3] += 1 # we want this key added

一个用例是简单计数,以避免集合的较高开销.计数器,但这个功能一般也是可取的.

反例[原谅双关语]

这是我想要的功能:

from collections import Counter
c = Counter()
res = c[5]  # 0
print(c)  # Counter()

c[8] = 1  # key added successfully
c[3] += 1 # key added successfully

但Counter比defaultdict(int)明显慢.我发现性能下降通常比defaultdict(int)慢约2倍.

另外,显然Counter只能与defaultdict中的int参数相媲美,而defaultdict可以采用list,set等.

有没有办法有效地实现上述行为;例如,通过继承defaultdict?

基准测试示例

%timeit DwD(lst)           # 72 ms
%timeit dd(lst)            # 44 ms
%timeit counter_func(lst)  # 98 ms
%timeit af(lst)            # 72 ms

测试代码:

import numpy as np
from collections import defaultdict,Counter,UserDict

class DefaultDict(defaultdict):
    def get_and_forget(self,key):
        _sentinel = object()
        value = self.get(key,_sentinel)

        if value is _sentinel:
            return self.default_factory()
        return value

class DictWithDefaults(dict):
    __slots__ = [''_factory'']  # avoid using extra memory

    def __init__(self,factory,*args,**kwargs):
        self._factory = factory
        super().__init__(*args,**kwargs)

    def __missing__(self,key):
        return self._factory()

lst = np.random.randint(0,10,100000)

def DwD(lst):
    d = DictWithDefaults(int)
    for i in lst:
        d[i] += 1
    return d

def dd(lst):
    d = defaultdict(int)
    for i in lst:
        d[i] += 1
    return d

def counter_func(lst):
    d = Counter()
    for i in lst:
        d[i] += 1
    return d

def af(lst):
    d = DefaultDict(int)
    for i in lst:
        d[i] += 1
    return d

关于赏金评论的注意事项:

自Bounty提供以来,@Aran-Fey’s solution已经更新,所以请忽略Bounty的评论.

解决方法

而不是搞乱 collections.defaultdict使它做我们想要的,似乎更容易实现我们自己:

class DefaultDict(dict):
    def __init__(self,default_factory,**kwargs):
        super().__init__(**kwargs)

        self.default_factory = default_factory

    def __getitem__(self,key):
        try:
            return super().__getitem__(key)
        except KeyError:
            return self.default_factory()

这可以按照您想要的方式工作:

d = DefaultDict(int)

res = d[5]
d[8] = 1 
d[3] += 1

print(d)  # {8: 1,3: 1}

但是,对于可变类型,它可能会出乎意料地表现:

d = DefaultDict(list)
d[5].append(''foobar'')

print(d)  # output: {}

这可能是defaultdict在访问不存在的密钥时记住该值的原因.

另一种选择是扩展defaultdict并添加一个新方法来查找值而不记住它:

from collections import defaultdict

class DefaultDict(defaultdict):
    def get_and_forget(self,key):
        return self.get(key,self.default_factory())

请注意,无论密钥是否已存在于dict中,get_and_forget方法每次都会调用default_factory().如果这是不合需要的,您可以使用sentinel值来实现它:

class DefaultDict(defaultdict):
    def get_and_forget(self,_sentinel)

        if value is _sentinel:
            return self.default_factory()
        return value

这样可以更好地支持可变类型,因为它允许您选择是否应该将值添加到dict中.

python – 将dict的键和值从str转换为Unicode的最快方法?

python – 将dict的键和值从str转换为Unicode的最快方法?

我正在使用集合导入计数器中的计数器,我想使用matplotlib.pylot打印它的值.

当我尝试使用时:

plt.bar(range(len(cnt)),cnt.values(),align='center')
plt.xticks(range(len(cnt)),cnt.keys())
plt.show()

我收到以下错误:

ValueError: matplotlib display text must have all code points < 128 or use Unicode strings

这就是我试图将Counter字典键转换为Unicode的原因.

解决方法

如果您使用的是Python 2.7,则可以使用dict理解:

unidict = {k.decode('utf8'): v.decode('utf8') for k,v in strdict.items()}

对于旧版本:

unidict = dict((k.decode('utf8'),v.decode('utf8')) for k,v in strdict.items())

(这假设你的字符串是UTF-8,当然.)

关于有没有任何pythonic方法可以组合两个dicts为两者中出现的键添加值?的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Effective Python - 用pythonic方式思考、ios – Swift:如何组合两个Dictionary实例?、python – 在collections.defaultdict中禁止键添加、python – 将dict的键和值从str转换为Unicode的最快方法?等相关知识的信息别忘了在本站进行查找喔。

本文标签: