V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
stupidcat
V2EX  ›  Python

如何在遍历 dict 时改变 dict 的大小?

  •  
  •   stupidcat · 2015-10-14 12:11:20 +08:00 · 3517 次点击
    这是一个创建于 3329 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 C++来表达的话,大致是这样:


    map<int, int> myMap;
    for (map<int, int>::iterator it = myMap.begin(); it != myMap.end(); ++it) {
    if(xxxx) {
    myMap[aa] = bb; //程序会保证添加进去的这项在迭代器当前位置的后面
    }
    }

    19 条回复    2015-10-14 23:51:54 +08:00
    stupidcat
        1
    stupidcat  
    OP
       2015-10-14 12:11:57 +08:00
    现在提示 RuntimeError: dictionary changed size during iteration
    wowpanda
        2
    wowpanda  
       2015-10-14 12:17:00 +08:00 via Android
    insert
    FrankFang128
        3
    FrankFang128  
       2015-10-14 12:19:46 +08:00 via Android
    一次只做一件事
    Ge4Los
        4
    Ge4Los  
       2015-10-14 12:38:06 +08:00   ❤️ 1
    字典的 key 没顺序啊,怎么插入到特定位置。
    若想改字典的大小,提供个思路,用字典生成式,创建个新字典。
    d2 = dict((k, v) for k, v in d1.items() if v > 100)
    d2 = {k:v for k ,v in d1.items() if v > 100}
    hahastudio
        5
    hahastudio  
       2015-10-14 12:40:14 +08:00   ❤️ 1
    这就是 implicit ,你是期望它只循环那些进 for 之前的 key, value 呢,还是说要把你可能加上的那些值也算上?

    没有歧义的做法是,先 deep copy 一个字典

    import copy
    new_dict = copy.deepcopy(origin_dict)
    for k,v in origin_dict:
    ....if blabla:
    ........new_dict[blablabla] = blablablabla

    refer:
    http://stackoverflow.com/questions/10107676/python-runtimeerror-dictionary-changed-size-during-iteration
    http://stackoverflow.com/questions/11941817/how-to-avoid-runtimeerror-dictionary-changed-size-during-iteration-error
    http://stackoverflow.com/questions/13519644/how-to-solve-dictionary-changed-size-during-iteration-in-python
    stupidcat
        6
    stupidcat  
    OP
       2015-10-14 13:04:24 +08:00
    @Ge4Los 好吧,我是按 C++迭代器的思路表达的。。。用迭代器遍历的话, key 是递增的,比如当前的 key 是 40 ,我保证添加进去的项的 key 大于 40 ,因而之后肯定会被遍历到
    stupidcat
        7
    stupidcat  
    OP
       2015-10-14 13:06:30 +08:00
    @hahastudio 我希望的就是像那个 C++代码一样,按 key 递增的方向遍历
    stupidcat
        8
    stupidcat  
    OP
       2015-10-14 13:13:01 +08:00
    @Ge4Los
    @hahastudio
    比如:
    现有一个 map<int, int> (1, 10), (2, 20), (5, 50), (7, 70)
    如果用 for (map<int, int>::iterator it = myMap.begin(); it != myMap.end(); ++it) 的话,会按照 key 从小到大的顺序来遍历
    我希望:
    如果我在程序遍历到(2, 20)的时候,往这个 map 里插入一项(3, 30),那么,下一次将会访问(3, 30),而不是(5, 50)
    如果我在程序遍历到(5, 50)的时候,往这个 map 里插入一项(0, 0),那么这一项将不会在本次 for 循环中被访问到

    用 python 该如何实现这个呢?
    EPr2hh6LADQWqRVH
        9
    EPr2hh6LADQWqRVH  
       2015-10-14 13:25:57 +08:00
    老老实实用计数器一个个+1
    deadEgg
        10
    deadEgg  
       2015-10-14 13:27:39 +08:00
    CopyOnWritreArrayList
    stupidcat
        11
    stupidcat  
    OP
       2015-10-14 13:30:48 +08:00
    暂时使用以下方法。。。
    list1 = list(dict1.keys())
    c = 0
    while c != len(list1):
    # some staff
    c += 1
    stupidcat
        12
    stupidcat  
    OP
       2015-10-14 13:31:26 +08:00
    list1 = list(dict1.keys())
    list1.sort()
    c = 0
    while c != len(list1):
    # some staff
    c += 1
    aisk
        13
    aisk  
       2015-10-14 13:33:03 +08:00   ❤️ 1
    waklin
        14
    waklin  
       2015-10-14 13:36:58 +08:00   ❤️ 1
    # -*- coding: utf-8 -*-
    d = {1:10, 2:20, 5:50, 7:70}

    i = 0
    while i < len(d):
    item = d.items()[i]
    if item[0] == 2:
    d.update({3:30})
    elif item[0] == 5:
    d.update({0:0})
    i += 1 # 当插入的项位于当前项之前时

    i += 1
    print item

    print d
    waklin
        15
    waklin  
       2015-10-14 13:40:25 +08:00
    v2ex 的 python 代码竟然不能缩进!
    上面代码运行结果如下

    (1, 10)
    (2, 20)
    (3, 30)
    (5, 50)
    (7, 70)
    {0: 0, 1: 10, 2: 20, 3: 30, 5: 50, 7: 70}

    ***Repl Closed***
    waklin
        16
    waklin  
       2015-10-14 13:51:16 +08:00   ❤️ 1
    安装了 chrome 插件,可以在回复中发图片了,测试一下
    hahastudio
        17
    hahastudio  
       2015-10-14 13:57:54 +08:00   ❤️ 1
    @stupidcat
    SGI STL 说 Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements ,这个是跟 Python 不一样的行为

    你这样定义的 OrderedDict 跟自带的还不太一样,你大概需要自己实现
    https://docs.python.org/2/library/collections.html#collections.OrderedDict
    Ge4Los
        18
    Ge4Los  
       2015-10-14 22:15:17 +08:00
    @stupidcat
    dict 遍历时不会保证输出元素的顺序, OrderedDict 才是有序的字典。
    WKPlus
        19
    WKPlus  
       2015-10-14 23:51:54 +08:00
    c++的 map 应该是红黑树实现的,是可以按顺序遍历的,而 python dict 其实是 hashmap ,是没有顺序的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2762 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 08:24 · PVG 16:24 · LAX 00:24 · JFK 03:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.