Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在python 3中实现OrderedDict的插入

如何在python 3中实现OrderedDict的插入
EN

Stack Overflow用户
提问于 2016-07-26 06:33:59
回答 4查看 7.2K关注 0票数 3

我想在某个位置将一个项目插入到OrderedDict中。使用要旨 of ,所以回答,我有一个问题,就是它不能在python3上工作。

这是使用的实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from collections import OrderedDict

class ListDict(OrderedDict):

    def __init__(self, *args, **kwargs):
        super(ListDict, self).__init__(*args, **kwargs)

    def __insertion(self, link_prev, key_value):
        key, value = key_value
        if link_prev[2] != key:
            if key in self:
                del self[key]
            link_next = link_prev[1]
            self._OrderedDict__map[key] = link_prev[1] = link_next[0] = [link_prev, link_next, key]
        dict.__setitem__(self, key, value)

    def insert_after(self, existing_key, key_value):
        self.__insertion(self._OrderedDict__map[existing_key], key_value)

    def insert_before(self, existing_key, key_value):
        self.__insertion(self._OrderedDict__map[existing_key][0], key_value)

把它当作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ld = ListDict([(1,1), (2,2), (3,3)])
ld.insert_before(2, (1.5, 1.5))

给出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
File "...", line 35, in insert_before
    self.__insertion(self._OrderedDict__map[existing_key][0], key_value)
AttributeError: 'ListDict' object has no attribute '_OrderedDict__map'

它适用于python2.7。它在python 3中失败的原因是什么?检查OrderedDict实现的源代码表明使用的是self.__map而不是self._OrderedDict__map。将代码更改为self.__map的用法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
AttributeError: 'ListDict' object has no attribute '_ListDict__map'

怎么会这样?我如何在python 3中实现这一点呢?OrderedDict使用内部__map属性存储双链接列表。那么,如何正确地访问这个属性呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-07-26 17:44:40

我不确定您是否会得到更好的服务,只需保持一个单独的列表并在代码中删除,但是下面是对这样一个对象的纯Python实现的尝试。这将比Python3.5中的实际OrderedDict慢一个数量级,正如我在评论已经用C重写了中指出的那样。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"""
A list/dict hybrid; like OrderedDict with insert_before and insert_after
"""
import collections.abc


class MutableOrderingDict(collections.abc.MutableMapping):
    def __init__(self, iterable_or_mapping=None, **kw):
        # This mimics dict's initialization and accepts the same arguments
        # Of course, you have to pass an ordered iterable or mapping unless you
        # want the order to be arbitrary. Garbage in, garbage out and all :)
        self.__data = {}
        self.__keys = []
        if iterable_or_mapping is not None:
            try:
                iterable = iterable_or_mapping.items()
            except AttributeError:
                iterable = iterable_or_mapping
            for key, value in iterable:
                self.__keys.append(key)
                self.__data[key] = value
        for key, value in kw.items():
            self.__keys.append(key)
            self.__data[key] = value

    def insert_before(self, key, new_key, value):
        try:
            self.__keys.insert(self.__keys.index(key), new_key)
        except ValueError:
            raise KeyError(key) from ValueError
        else:
            self.__data[new_key] = value

    def insert_after(self, key, new_key, value):
        try:
            self.__keys.insert(self.__keys.index(key) + 1, new_key)
        except ValueError:
            raise KeyError(key) from ValueError
        else:
            self.__data[new_key] = value

    def __getitem__(self, key):
        return self.__data[key]

    def __setitem__(self, key, value):
        self.__keys.append(key)
        self.__data[key] = value

    def __delitem__(self, key):
        del self.__data[key]
        self.__keys.remove(key)

    def __iter__(self):
        return iter(self.__keys)

    def __len__(self):
        return len(self.__keys)

    def __contains__(self, key):
        return key in self.__keys

    def __eq__(self, other):
        try:
            return (self.__data == dict(other.items()) and
                    self.__keys == list(other.keys()))
        except AttributeError:
            return False

    def keys(self):
        for key in self.__keys:
            yield key

    def items(self):
        for key in self.__keys:
            yield key, self.__data[key]

    def values(self):
        for key in self.__keys:
            yield self.__data[key]

    def get(self, key, default=None):
        try:
            return self.__data[key]
        except KeyError:
            return default

    def pop(self, key, default=None):
        value = self.get(key, default)
        self.__delitem__(key)
        return value

    def popitem(self):
        try:
            return self.__data.pop(self.__keys.pop())
        except IndexError:
            raise KeyError('%s is empty' % self.__class__.__name__)


    def clear(self):
        self.__keys = []
        self.__data = {}

    def update(self, mapping):
        for key, value in mapping.items():
            self.__keys.append(key)
            self.__data[key] = value

    def setdefault(self, key, default):
        try:
            return self[key]
        except KeyError:
            self[key] = default
            return self[key]

    def __repr__(self):
        return 'MutableOrderingDict(%s)' % ', '.join(('%r: %r' % (k, v)
                                                      for k, v in self.items()))

我最终实现了整个collections.abc.MutableMapping契约,因为没有一个方法很长,但是您可能不会全部使用它们。特别是,__eq__popitem有点任意性。我将您在insert_*方法上的签名更改为一个对我来说更自然的4参数参数。最后注意事项:只在Python3.5上测试。当然,如果没有一些(小的)更改,Python 2将无法工作。

票数 3
EN

Stack Overflow用户

发布于 2019-03-26 19:14:24

在3.7中尝试新的dict对象,并认为我会尝试实现两位炼金术士对他的答案所做的事情,但只是覆盖本地dict类,因为3.7 dict是有序的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
''' Script that extends python3.7 dictionary to include insert_before and insert_after methods. '''
from sys import exit as sExit

class MutableDict(dict):
    ''' Class that extends python3.7 dictionary to include insert_before and insert_after methods. '''

    def insert_before(self, key, newKey, val):
        ''' Insert newKey:value into dict before key'''
        try:
            __keys = list(self.keys())
            __vals = list(self.values())

            insertAt = __keys.index(key)

            __keys.insert(insertAt, newKey)
            __vals.insert(insertAt, val)

            self.clear()
            self.update({x: __vals[i] for i, x in enumerate(__keys)})

        except ValueError as e:
            sExit(e)

    def insert_after(self, key, newKey, val):
        ''' Insert newKey:value into dict after key'''
        try:
            __keys = list(self.keys())
            __vals = list(self.values())

            insertAt = __keys.index(key) + 1

            if __keys[-1] != key:
                __keys.insert(insertAt, newKey)
                __vals.insert(insertAt, val)
                self.clear()
                self.update({x: __vals[i] for i, x in enumerate(__keys)})
            else:
                self.update({newKey: val})

        except ValueError as e:
            sExit(e)

一个小小的测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 In: v = MutableDict([('a', 1), ('b', 2), ('c', 3)])
Out: {'a': 1, 'b': 2, 'c': 3}

 In: v.insert_before('a', 'g', 5)
Out: {'g': 5, 'a': 1, 'b': 2, 'c': 3}

 In: v.insert_after('b', 't', 5)
Out: {'g': 5, 'a': 1, 'b': 2, 't': 5, 'c': 3}

编辑:我决定做一个小小的基准测试,看看这会给性能带来什么样的影响。我将使用from timeit import timeit

找个基线。创建一个具有任意值的数据集。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 In: timeit('{x: ord(x) for x in string.ascii_lowercase[:27]}', setup='import string', number=1000000)
Out: 1.8214202160015702

看看用与以前相同的任意值初始化MutableDict需要多长时间。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 In: timeit('MD({x: ord(x) for x in string.ascii_lowercase[:27]})', setup='import string; from MutableDict import MutableDict as MD', number=1000000)
Out: 2.382507269998314

1.82 / 2.38 = 0.76。所以如果我考虑这个问题的话,MutableDict的创建速度会慢24%。

让我们看看做一个插入需要多长时间。对于这个测试,我将使用insert_after方法,因为它稍微大一些。还将查找接近末尾的键以进行插入。在这个案子里没有。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 In: timeit('v.insert_after("t", "zzrr", ord("z"))', setup='import string; from MutableDict import MutableDict as MD; v = MD({x: ord(x) for x in string.ascii_lowercase[:27]})' ,number=1000000)
Out: 3.9161406760104

2.38 / 3.91 = 0.60,比初始化慢40%。在一百万圈的小测试中还不错。为了比较时间关系,我们将测试以下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 In: timeit('"-".join(map(str, range(100)))', number=1000000)
Out: 10.342204540997045

不完全是比较,但我希望这些测试将有助于您(读者,不一定是OP)决定在3.7项目中使用或不使用该类。

票数 3
EN

Stack Overflow用户

发布于 2016-10-18 13:35:30

从Python3.2开始,move_to_end可以用于在OrderedDict中移动项目。下面的代码将通过将提供的索引后的所有项移到末尾来实现insert功能。

请注意,这不是非常有效,应该谨慎使用(如果有的话)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def ordered_dict_insert(ordered_dict, index, key, value):
    if key in ordered_dict:
        raise KeyError("Key already exists")
    if index < 0 or index > len(ordered_dict):
        raise IndexError("Index out of range")

    keys = list(ordered_dict.keys())[index:]
    ordered_dict[key] = value
    for k in keys:
        ordered_dict.move_to_end(k)

有明显的优化和改进可以进行,但这是总的想法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38592779

复制
相关文章
MySQL 特殊字符
SQL 注释是用来在 SQL 语句中添加对代码的解释说明。SQL 支持两种类型的注释符号。
恋喵大鲤鱼
2023/10/12
1K0
BashShell常量和特殊字符
其中,base 是一个 2 到 64 的十进制数值,表示数字的基数;n 是在 base 基数中的数字的值。如果忽略 base# ,则默认以 10 为基数。n 中的每一位数如果大于 9,则依次以小写字母、大写字母、@、_ 表示(最大表示到十进制中的 63,因为 base 最大为 64)。
hotarugali
2022/02/28
5.6K0
LaTeX特殊字符和符号
无论什么字体,LaTeX以一个反勾号或重音符(`)当做左引号,以一个正勾号或直立引号(')当做右引号。
hotarugali
2022/03/17
6.2K0
LaTeX特殊字符和符号
Mysql去除字符串中的特殊字符及varchar转int
Mysql中有varchar类型字段,并且为:123,456 形式,需要对其进行排序,并根据条件筛选出前5条
itze
2022/10/31
3.6K0
Shell特殊字符
shell既是类Unix操作系统的命令解析器,用于解释执行用户输入的一连串命令,它类似于DOS下的command和后来Windows的cmd.exe。同时shell也是一种程序设计语言。作为命令解释型的脚本语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它预定义了各种环境变量,保留了一些关键字以及一些特殊字符的含义,并提供了许多在高级语言中才具有的控制结构,包括循环和分支判断。
恋喵大鲤鱼
2018/08/03
5.2K0
HTML特殊字符
HTML 原始码 显示结果 描述 &lt; < 小於号或显示标记 &gt; > 大於号或显示标记 &amp; & 可用於显示其它特殊字符 &quot; " 引号 &reg; ® 己注册 &copy; © 版权 &trade; ™ 商标 &ensp; 半方大的空白 &emsp; 全方大的空白 &nbsp; 不断行的空白
小小许
2018/09/20
3.7K0
常用的HTML和CSS(content)特殊字符图标
​之前折腾WordPress主题的时候感觉Font Awesome太过庞大,好多图标字体基本都用不上,加载起来太慢了,于是自己折腾了一套简单的图标字体,但在完善主题过程中才发现字体太少不够用(有些图标当时没想到),重新折腾又要重新来一次太麻烦。于是想到可以用css的content,通过伪元素将一些符合的unicode字符集插入其中。
楚客追梦
2022/10/30
3.6K0
Shell常用的特殊字符
点号在不同场景有着不同的含义,在目录路径中,一个点代表当前工作目录,两个点代表父目录;当一个文件以点号开头,表示一个隐藏文件;在正则表达式,点号代表匹配单个字符;
用户1679793
2020/10/29
8.1K0
常用的HTML和CSS(content)特殊字符图标
之前折腾主题的时候感觉Font Awesome太过庞大,好多图标字体基本都用不上,加载起来太慢了,于是自己折腾了一套简单的图标字体,但在完善主题过程中才发现字体太少不够用(有些图标当时没想到),重新折腾又要重新来一次太麻烦。于是想到可以用css的content,通过伪元素将一些符合的unicode字符集插入其中。
楚客追梦
2022/11/11
4.6K0
JXL读写Excel
使用JXL生成Excel文 package test.jxl; import jxl.Workbook; import jxl.write.Label; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import org.apache.commons.lang3.RandomStringUtils; import java.io.File; impor
前Thoughtworks-杨焱
2021/12/08
2800
Makefile中特殊字符和关键字
.Phony 是一个特殊的工作目标,它后面的并不是一个实际文件名:只是在显式请求时执行命令的名字;而且肯定要视为未更新。使用 .Phony 的原因在于:
hotarugali
2022/03/11
8380
AJAX传递特殊字符的方法
AJAX传递特殊字符的方法 采用Ajax传递参数加号(+)和与符号(&)时候,服务端获取到的参数并不如意! (1) "+"号:JavaScript解析为字符串连接符,所以服务器端接收数据时"+"会丢失。 (2)"&":JavaScript解析为变量连接符,所以服务器端接收数据时&符号以后的数据都会丢失。 解决办法:在传到服务端之前先将参数中的"+"和"&"符号都编码一下 function filter(str) { str = str.replace(/\+/g,"%2B"); str =
wangxl
2018/03/07
2.8K0
java 对于表情和特殊字符的转码解码处理
转码然后插入到DB当中 String encodestr=URLEncoder.encode("需要转码的内容", "utf-8") 将encodestr插入数据库中 解码然后显示到页面当中 String decodestr=URLDecoder.decode("需要解码的内容", "utf-8") 在页面展示decodestr
用户4191150
2021/08/12
3.8K1
插入"&"特殊字符的几种思考
一位铁杆朋友,今天问了个问题,写了一个Python程序,从文件读取数据,其中可能包含“&”这种特殊字符,为了让其能插入Oracle,需要做什么处理?
bisal
2020/04/02
2.3K0
mysql命令创建数据库库名特殊字符
在使用mysql命令进行数据库创建时,发现“-”等特殊字符无法使用,提示sql语句语法错误。
程序新视界
2022/05/06
2.8K0
特殊字符乱码问题
1、使用标签 建议用(标签可以控制转换特殊字符): <html:text property=“instruction” readonly=“true” styleClass=“mylongreadonly” size=“32”/> <input name=“instruction” type=“hidden” value=”<mycim2:write name=“object” property=“instruction” filter=“true”/>” > <input name=“instruction” type=“hidden” value=”<bean:write name=“object” property=“instruction” filter=“true”/>” >
全栈程序员站长
2022/06/27
2.7K0
iOS去除特殊字符
// 清除特殊字符 + (NSString *)cleanSpecialCharacters:(NSString *)text { NSString *strResult = nil; NSMutableString *originString = [text mutableCopy]; NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"~!@#$%^&*()+={}':;',[]\\.
Raindew
2019/05/17
3.3K0
转义JavaScript特殊字符
大家可以举一反三,触类旁通,反正,双引号和单引号可以配合着使用,把我上面的案例看懂,你就能灵活的运用了。
IT工作者
2022/01/05
4.1K0
点击加载更多

相似问题

Rails 3 AJAX问题- UJS

10

jquery_ujs和rails的问题-ujs问题ajax页面

218

基本UJS AJAX Rails 3.0更新问题

22

Rails UJS ajax:完全不触发

13

Rails UJS与URL params问题

12
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文