defaultdict equivalent for lists [duplicate]

一曲冷凌霜 提交于 2019-12-08 15:48:48

问题


Is there\How would you build an equivalent of python's very useful collections.defaultdict?

Imagined usage of such a container:

>>> a = collections.defaultlist(0)
>>> a[2]=7
>>> a[4]='x'
>>> a
[0,0,7,0,'x']

UPDATE: I've added a follow up question to add even more functionality to this construct


回答1:


I think this would be a bit confusing to use; however, here's my first thought on how to do it:

class defaultlist(list):
    def __init__(self, fx):
        self._fx = fx

    def __setitem__(self, index, value):
        while len(self) <= index:
            self.append(self._fx())
        list.__setitem__(self, index, value)

This takes a callable (I think that's how defaultdict works) for the default value.

When I run:

a = defaultlist(int)
print a
a[2] = 7
a[4] = 'x'
print a

I get back:

[]
[0, 0, 7, 0, 'x']



回答2:


If all you need is indexed access and not slicing / append, etc, then just use a defaultdict.

(if you really want perl / js semantics on this, you could subclass list __get__ and __set__)




回答3:


My proposal:

def xtend(f):
    def wrap(self, index, *args):
        if len(self) <= index:
            self.extend([self._gen()] * (index - len(self) + 1))
        return f(self, index, *args)
    return wrap

class defaultlist(list):
    def __init__(self, gen, lst = []):
        list.__init__(self, lst)
        self._gen = gen

    __setitem__ = xtend(list.__setitem__)
    __getitem__ = xtend(list.__getitem__)

Results:

>>> a = defaultlist(int, [1, 2, 3])
>>> a[10] = 'x'
>>> a[2] = 7
>>> print a
[1, 2, 7, 0, 0, 0, 0, 0, 0, 0, 'x']



回答4:


A slightly enhanced version from answer by @Finn.

class defaultlist(list):
    """List returning default value when accessing uninitialized index.

    Original implementation: http://stackoverflow.com/a/8719940/315168
    """

    def __init__(self, fx):
        self._fx = fx

    def __setitem__(self, index, value):
        while len(self) <= index:
            self.append(self._fx())
        list.__setitem__(self, index, value)

    def __getitem__(self, index):
        """Allows self.dlist[0] style access before value is initialized."""
        while len(self) <= index:
            self.append(self._fx())
        return list.__getitem__(self, index)



回答5:


Perhaps the easiest way is using a dict:

>>> a = {}
>>> a[2] = 7
>>> a[4] = 'x'
>>> [a[i] if i in a else 0 for i in xrange(max(a) + 1)]
[0, 0, 7, 0, 'x']


来源:https://stackoverflow.com/questions/8719558/defaultdict-equivalent-for-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!