odict#
- class odict(*args, defaultdict=None, **kwargs)[source]#
Bases:
dict
Ordered dictionary with integer indexing
An ordered dictionary, like the OrderedDict class, but supports list methods like integer indexing, key slicing, and item inserting. It can also replicate defaultdict behavior via the
defaultdict
argument.- Parameters:
Examples:
# Simple example mydict = sc.odict(foo=[1,2,3], bar=[4,5,6]) # Assignment is the same as ordinary dictionaries mydict['foo'] == mydict[0] # Access by key or by index mydict[:].sum() == 21 # Slices are returned as numpy arrays by default for i,key,value in mydict.enumitems(): # Additional methods for iteration print(f'Item {i} is named {key} and has value {value}') # Detailed example foo = sc.odict({'ant':3,'bear':4, 'clam':6, 'donkey': 8}) # Create odict bar = foo.sorted() # Sort the dict assert bar['bear'] == 4 # Show get item by value assert bar[1] == 4 # Show get item by index assert (bar[0:2] == [3,4]).all() # Show get item by slice assert (bar['clam':'donkey'] == [6,8]).all() # Show alternate slice notation assert (bar[np.array([2,1])] == [6,4]).all() # Show get item by list assert (bar[:] == [3,4,6,8]).all() # Show slice with everything assert (bar[2:] == [6,8]).all() # Show slice without end bar[3] = [3,4,5] # Show assignment by item bar[0:2] = ['the', 'power'] # Show assignment by slice bar[[0,3]] = ['hill', 'trip'] # Show assignment by list bar.rename('clam','oyster') # Show rename print(bar) # Print results # Defaultdict examples dd = sc.odict(a=[1,2,3], defaultdict=list) dd['c'].append(4) nested = sc.odict(a=0, defaultdict='nested') # Create a infinitely nested dictionary (NB: may behave strangely on IPython) nested['b']['c']['d'] = 2
Note: by default, integers are used as an alias to string keys, so cannot be used as keys directly. However, you can force regular-dict behavior using
setitem()
, and you can convert a dictionary with integer keys to an odict usingsc.odict.makefrom()
. If an odict has integer keys and the keys do not match the key positions, then the key itself will take precedence (e.g.,od[3]
is equivalent todict(od)[3]
, notdict(od)[od.keys()[3]]
). This usage is discouraged.New in version 1.1.0: “defaultdict” argumentNew in version 1.3.1: allow integer keys viamakefrom()
; removedto_OD
; performance improvementsNew in version 2.0.1: allow deletion by indexNew in version 3.0.0: allow numeric indices; inherit from dict rather than OrderedDictMethods
- __add__(dict2)[source]#
Allow two dictionaries to be added (merged).
Example:
dict1 = sc.odict(a=3, b=4) dict2 = sc.odict(c=5, d=7) dict3 = dict1 + dict2
- disp(maxlen=None, showmultilines=True, divider=False, dividerthresh=10, numindents=0, sigfigs=5, numformat=None, maxitems=20, **kwargs)[source]#
Print out flexible representation, short by default.
Example:
z = sc.odict().make(keys=['a','b','c'], vals=[4.293487,3,6]) z.disp(sigfigs=3) z.disp(numformat='%0.6f')
- export(doprint=True, classname='odict')[source]#
Export the odict in a form that is valid Python code
- pop(key, *args, **kwargs)[source]#
Allows pop to support strings, integers, slices, lists, or arrays
- findkeys(pattern=None, method=None, first=None)[source]#
Find all keys that match a given pattern. By default uses regex, but other options are ‘find’, ‘startswith’, ‘endswith’. Can also specify whether or not to only return the first result (default false). If the key is a tuple instead of a string, it will search each element of the tuple.
- findbykey(pattern=None, method=None, first=True)[source]#
Same as findkeys, but returns values instead
- findbyval(value, first=True, strict=False)[source]#
Returns the key(s) that match a given value – reverse of findbykey, except here uses exact matches to the value or values provided.
Example:
z = sc.odict({'dog':[2,3], 'cat':[4,6], 'mongoose':[4,6]}) z.findbyval([4,6]) # returns 'cat' z.findbyval([4,6], first=False) # returns ['cat', 'mongoose']
- filter(keys=None, pattern=None, method=None, exclude=False)[source]#
Find matching keys in the odict, and return a new odict
Filter the odict keys and return a new odict which is a subset. If keys is a list, then uses that for matching. If the first argument is a string, then treats as a pattern for matching using
findkeys() <odict.findkeys()
.- Parameters:
keys (list) – the list of keys to keep (or exclude)
pattern (str) – the pattern by which to match keys; see
findkeys() <odict.findkeys()
for detailsmethod (str) – the method by which to match keys; see
findkeys() <odict.findkeys()
for detailsexclude (bool) – if exclude=True, then exclude rather than include matches
See also
sort()
, which includes filtering by position.
- insert(pos=None, key=None, value=None)[source]#
Function to do insert a key – note, computationally inefficient.
Example:
z = sc.odict() z['foo'] = 1492 z.insert(1604) z.insert(0, 'ganges', 1444) z.insert(2, 'mekong', 1234)
- sort(sortby=None, reverse=False, copy=False)[source]#
Create a sorted version of the odict.
By default, this method sorts alphabetically by key, but many other options are possible:
‘keys’ sorts alphabetically by key
‘values’ sorts in ascending order by value
if a list of keys is provided, sort by that order (any keys not provided will be omitted from the sorted dict!)
if a list of numbers is provided, treat these as indices and sort by that order
if a list of boolean values is provided, then omit False entries
- Parameters:
For filtering by string matching on keys, see
filter()
.New in version 3.0.0: removed “verbose” argument
- sorted(sortby=None, reverse=False)[source]#
Shortcut for making a copy of the sorted odict – see
sort()
for options
- make(keys=None, vals=None, keys2=None, keys3=None, coerce='full')[source]#
An alternate way of making or adding to an odict.
- Parameters:
keys (list/int) – the list of keys to use
vals (list/arr) – the list of values to use
keys2 (list/int) – for a second level of nesting
keys3 (list/int) – for a third level of nesting
coerce (str) – what types to coerce into being separate dict entries
Examples:
a = sc.odict().make(5) # Make an odict of length 5, populated with Nones and default key names b = sc.odict().make('foo',34) # Make an odict with a single key 'foo' of value 34 c = sc.odict().make(['a','b']) # Make an odict with keys 'a' and 'b' d = sc.odict().make(['a','b'], 0) # Make an odict with keys 'a' and 'b', initialized to 0 e = sc.odict().make(keys=['a','b'], vals=[1,2]) # Make an odict with 'a':1 and 'b':2 f = sc.odict().make(keys=['a','b'], vals=np.array([1,2])) # As above, since arrays are coerced into lists g = sc.odict({'a':34, 'b':58}).make(['c','d'],[99,45]) # Add extra keys to an exising odict h = sc.odict().make(keys=['a','b','c'], keys2=['A','B','C'], keys3=['x','y','z'], vals=0) # Make a triply nested odict
New in version 1.2.2: “coerce” argument
- classmethod makefrom(source=None, include=None, keynames=None, force=True, *args, **kwargs)[source]#
Create an odict from entries in another dictionary. If keys is None, then use all keys from the current dictionary.
- Parameters:
source (dict/list/etc) – the item(s) to convert to an odict
include (list) – list of keys to include from the source dict in the odict (default: all)
keynames (list) – names of keys if source is not a dict
force (bool) – whether to force conversion to an odict even if e.g. the source has numeric keys
Examples:
a = 'cat' b = 'dog' o = sc.odict.makefrom(source=locals(), include=['a','b']) # Make use of fact that variables are stored in a dictionary d = {'a':'cat', 'b':'dog'} o = sc.odict.makefrom(d) # Same as sc.odict(d) l = ['cat', 'monkey', 'dog'] o = sc.odict.makefrom(source=l, include=[0,2], keynames=['a','b']) d = {12:'monkeys', 3:'musketeers'} o = sc.odict.makefrom(d)
- map(func=None)[source]#
Apply a function to each element of the odict, returning a new odict with the same keys.
Example:
cat = sc.odict({'a':[1,2], 'b':[3,4]}) def myfunc(mylist): return [i**2 for i in mylist] dog = cat.map(myfunc) # Returns odict({'a':[1,4], 'b':[9,16]})
- fromeach(ind=None, asdict=True)[source]#
Take a “slice” across all the keys of an odict, applying the same operation to entry. The simplest usage is just to pick an index. However, you can also use it to apply a function to each key.
Example:
z = sc.odict({'a':array([1,2,3,4]), 'b':array([5,6,7,8])}) z.fromeach(2) # Returns array([3,7]) z.fromeach(ind=[1,3], asdict=True) # Returns odict({'a':array([2,4]), 'b':array([6,8])})
- toeach(ind=None, val=None)[source]#
The inverse of fromeach: partially reset elements within each odict key.
Example:
z = sc.odict({'a':[1,2,3,4], 'b':[5,6,7,8]}) z.toeach(2, [10,20]) # z is now odict({'a':[1,2,10,4], 'b':[5,6,20,8]}) z.toeach(ind=3,val=666) # z is now odict({'a':[1,2,10,666], 'b':[5,6,20,666]})
- enumkeys(transpose=False)[source]#
Shortcut for enumerate(odict.keys()).
If transpose=True, return a tuple of lists rather than a list of tuples.
- enumvals(transpose=False)[source]#
Shortcut for enumerate(odict.values())
If transpose=True, return a tuple of lists rather than a list of tuples.
- enumitems(transpose=False)[source]#
Returns tuple of 3 things: index, key, value.
If transpose=True, return a tuple of lists rather than a list of tuples.
- classmethod promote(obj=None)[source]#
Like promotetolist, but for odicts.
Example:
od = sc.odict.promote(['There','are',4,'keys'])
Note, in most cases sc.odict(obj) or sc.odict().make(obj) can be used instead.
- makenested(*args, **kwargs)[source]#
Alias to sc.makenested(odict); see sc.makenested() for full documentation. New in version 1.2.0.
- getnested(*args, **kwargs)[source]#
Alias to sc.getnested(odict); see sc.makenested() for full documentation. New in version 1.2.0.