I'm wondering if there is a way of using a lambda like style to append to a dictionarie's list field sorted.
Example:
a = {}
a.setdefault("foo", []).append(2)
a.setdefault("foo", []).append(1)
{'foo': [2, 1]}
Is there a way of doing an insert in sorted order
as using a["foo"].bisect.insort(a, -1)
, so that I don't need to call sort afterwards?
All you need is in Pythons standard library:
import bisect
from collections import defaultdict
def add(dd, key, value):
bisect.insort_left(dd[key], value)
a = defaultdict(list)
add(a, "foo", 3)
add(a, "foo", 2)
add(a, "foo", 1)
add(a, "foo", 3)
add(a, "foo", 2)
add(a, "foo", 1)
assert a["foo"] == sorted(a["foo"])
print(a)
if you want a lambda:
add = lambda dd, key, value: bisect.insort_left(dd[key], value)
In terms of performance using sort
afterwards runtime should be faster than using bisect.insort_left
. In both cases runtime complexity is O(n log n) but function call overhead should result in different absolute run times.
You could use collections.defaultdict
instead, with some SortedList
implementation (downloaded with pip install sortedcontainers
, but there are others):
import collections
from sortedcontainers import SortedList
a = collections.defaultdict(SortedList)
a["foo"].add(2)
a["foo"].add(1)
print(a)
result:
defaultdict(<class 'sortedcontainers.sortedlist.SortedList'>, {'foo': SortedList([1, 2])})
you could override add
by append
if you have a lot of code to refactor.
note that it also works with setdefault
, but more cumbersome:
a = {}
a.setdefault("foo", SortedList()).add(2)
a.setdefault("foo", SortedList()).add(1)
(and doing that on a lot of elements has the disadvantage of creating a SortedList()
object just in case the key doesn't exist)
While you can do this, with a helper function:
def list_append(lst, item):
lst.append(item)
return lst
a = {}
list_append(a.setdefault("foo", []), 2).sort()
list_append(a.setdefault("foo", []), 1).sort()
But I will definitely recommend you try other data structure, like heapq
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.