Reputation: 13485
I find myself often in need of a flexible data structure which is something between a dict and an array. I hope the following example will illustrate:
a = ArrayStruct()
a['a', 'aa1'] = 1
a['a', 'aa2'] = 2
a['b', 0, 'subfield1'] = 4
a['b', 0, 'subfield2'] = 5
a['b', 1, 'subfield1'] = 6
a['b', 1, 'subfield2'] = 7
assert a['a', 'aa2'] == 2
assert all(a['b', 1, :] == [6, 7])
assert all(a['b', :, 'subfield1'] == [4, 6])
assert all(a['b', :, :] == [[4, 5], [6, 7]])
with pytest.raises(KeyError): # This should raise an error because key 'a' does not have subkeys 1, 'subfield1'
x = a[:, 1, 'subfield1']
Before I go and (re)invent the wheel. Is there an existing Python package that implements this kind of data structure?
Upvotes: 2
Views: 3172
Reputation: 13485
I made it myself. It's called a Duck. It currently lives in master branch of Artemis. Here's some code demonstrating its use:
from artemis.general.duck import Duck
import numpy as np
import pytest
# Demo 1: Dynamic assignment
a = Duck()
a['a', 'aa1'] = 1
a['a', 'aa2'] = 2
a['b', 0, 'subfield1'] = 4
a['b', 0, 'subfield2'] = 5
a['b', 1, 'subfield1'] = 6
a['b', 1, 'subfield2'] = 7
assert list(a['b', 1, :]) == [6, 7]
assert a['b', :, 'subfield1'] == [4, 6]
assert a['a', 'aa2'] == 2
assert np.array_equal(a['b'].to_array(), [[4, 5], [6, 7]])
with pytest.raises(KeyError): # This should raise an error because key 'a' does not have subkeys 1, 'subfield1'
x = a[:, 1, 'subfield1']
# Demo 2: Sequential and Sliced Assignment
# Here we show another way to create the same structure as above
# 1) You can assign to a slice
# 2) You can use the "next" builtin like an index to append to the structure.
b = Duck()
b['a', :] = {'aa1': 1, 'aa2': 2} # Note: when assigning with dict, keys are sorted before insertion (OrderedDict order is kept though).
b['b', next, :] = {'subfield1': 4, 'subfield2': 5}
b['b', next, :] = {'subfield1': 6, 'subfield2': 7}
assert b==a
Upvotes: 3