Package iceprod :: Package core :: Module odict :: Class OrderedDict
[hide private]
[frames] | no frames]

Class OrderedDict

source code

object --+    
         |    
      dict --+
             |
            OrderedDict
Known Subclasses:


A class of dictionary that keeps the insertion order of keys.

All appropriate methods return keys, items, or values in an ordered way.

All normal dictionary methods are available. Update and comparison is
restricted to other OrderedDict objects.

Various sequence methods are available, including the ability to explicitly
mutate the key ordering.

__contains__ tests:

>>> d = OrderedDict(((1, 3),))
>>> 1 in d
1
>>> 4 in d
0

__getitem__ tests:

>>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2]
1
>>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4]
Traceback (most recent call last):
KeyError: 4

__len__ tests:

>>> len(OrderedDict())
0
>>> len(OrderedDict(((1, 3), (3, 2), (2, 1))))
3

get tests:

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.get(1)
3
>>> d.get(4) is None
1
>>> d.get(4, 5)
5
>>> d
OrderedDict([(1, 3), (3, 2), (2, 1)])

has_key tests:

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.has_key(1)
1
>>> d.has_key(4)
0

Instance Methods [hide private]
new empty dictionary

__init__(self, init_val=(), strict=False)
Create a new ordered dictionary.
source code
 
__delitem__(self, key)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__eq__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__lt__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__le__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__ne__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__gt__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__ge__(self, other)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
 
__repr__(self)
Used for __repr__ and __str__
source code
 
__setitem__(self, key, val)
Allows slice assignment, so long as the slice is an OrderedDict >>> d = OrderedDict() >>> d['a'] = 'b' >>> d['b'] = 'a' >>> d[3] = 12 >>> d OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)]) >>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4))) >>> d OrderedDict([(1, 2), (2, 3), (3, 4)]) >>> d[::2] = OrderedDict(((7, 8), (9, 10))) >>> d OrderedDict([(7, 8), (2, 3), (9, 10)]) >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4))) >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) >>> d OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True) >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) >>> d OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
source code
 
__getitem__(self, key)
Allows slicing.
source code
 
__str__(self)
Used for __repr__ and __str__
source code
 
__setattr__(self, name, value)
Implemented so that accesses to ``sequence`` raise a warning and are diverted to the new ``setkeys`` method.
source code
 
__getattr__(self, name)
Implemented so that access to ``sequence`` raises a warning.
source code
 
__deepcopy__(self, memo)
To allow deepcopy to work with OrderedDict.
source code
a shallow copy of D
copy(self)
>>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy()...
source code
list of D's (key, value) pairs, as 2-tuples
items(self)
``items`` returns a list of tuples representing all the ``(key, value)`` pairs in the dictionary.
source code
list of D's keys
keys(self)
Return a list of keys in the ``OrderedDict``.
source code
list of D's values
values(self, values=None)
Return a list of all the values in the OrderedDict.
source code
an iterator over the (key, value) items of D
iteritems(self)
>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems()...
source code
an iterator over the keys of D
iterkeys(self)
>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()...
source code
an iterator over the keys of D
__iter__(self)
>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()...
source code
an iterator over the values of D
itervalues(self)
>>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues()...
source code
None
clear(self)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
v, remove specified key and return the corresponding value
pop(self, key, *args)
No dict.pop in Python 2.2, gotta reimplement it
source code
(k, v), remove and return some (key, value) pair as a
popitem(self, i=-1)
Delete and return an item specified by index, not a random one as in dict.
source code
D.get(k,d), also set D[k]=d if k not in D
setdefault(self, key, defval=None)
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))...
source code
None
update(self, from_od)
Update from another OrderedDict or sequence of (key, value) pairs
source code
 
setitems(self, items)
This method allows you to set the items in the dict.
source code
 
setkeys(self, keys)
``setkeys`` all ows you to pass in a new list of keys which will replace the current set.
source code
 
setvalues(self, values)
You can pass in a list of values, which will replace the current list.
source code
 
index(self, key)
Return the position of the specified key in the OrderedDict.
source code
 
insert(self, index, key, value)
Takes ``index``, ``key``, and ``value`` as arguments.
source code
 
reverse(self)
Reverse the order of the OrderedDict.
source code
 
sort(self, *args, **kwargs)
Sort the key order in the OrderedDict.
source code

Inherited from dict: __cmp__, __contains__, __getattribute__, __hash__, __len__, __new__, fromkeys, get, has_key

Inherited from object: __delattr__, __reduce__, __reduce_ex__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, init_val=(), strict=False)
(Constructor)

source code 

Create a new ordered dictionary. Cannot init from a normal dict,
nor from kwargs, since items order is undefined in those cases.

If the ``strict`` keyword argument is ``True`` (``False`` is the
default) then when doing slice assignment - the ``OrderedDict`` you are
assigning from *must not* contain any keys in the remaining dict.

>>> OrderedDict()
OrderedDict([])
>>> OrderedDict({1: 1})
Traceback (most recent call last):
TypeError: undefined order, cannot get items from dict
>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d
OrderedDict([(1, 3), (3, 2), (2, 1)])
>>> OrderedDict(d)
OrderedDict([(1, 3), (3, 2), (2, 1)])

Returns:
new empty dictionary

Overrides: object.__init__

__delitem__(self, key)
(Index deletion operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> del d[3]
>>> d
OrderedDict([(1, 3), (2, 1)])
>>> del d[3]
Traceback (most recent call last):
KeyError: 3
>>> d[3] = 2
>>> d
OrderedDict([(1, 3), (2, 1), (3, 2)])
>>> del d[0:1]
>>> d
OrderedDict([(2, 1), (3, 2)])

Overrides: dict.__delitem__

__eq__(self, other)
(Equality operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d == OrderedDict(d)
1
>>> d == OrderedDict(((1, 3), (2, 1), (3, 2)))
0
>>> d == OrderedDict(((1, 0), (3, 2), (2, 1)))
0
>>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
0
>>> d == dict(d)
Traceback (most recent call last):
TypeError: Equality undefined for OrderedDicts and dictionaries
>>> d == False
0

Overrides: dict.__eq__

__lt__(self, other)
(Less-than operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
>>> c < d
1
>>> d < c
0
>>> d < dict(c)
Traceback (most recent call last):
TypeError: Can only compare with other OrderedDicts

Overrides: dict.__lt__

__le__(self, other)
(Less-than-or-equals operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
>>> e = OrderedDict(d)
>>> c <= d
1
>>> d <= c
0
>>> d <= dict(c)
Traceback (most recent call last):
TypeError: Can only compare with other OrderedDicts
>>> d <= e
1

Overrides: dict.__le__

__ne__(self, other)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d != OrderedDict(d)
0
>>> d != OrderedDict(((1, 3), (2, 1), (3, 2)))
1
>>> d != OrderedDict(((1, 0), (3, 2), (2, 1)))
1
>>> d == OrderedDict(((0, 3), (3, 2), (2, 1)))
0
>>> d != dict(d)
Traceback (most recent call last):
TypeError: Inequality undefined for OrderedDicts and dictionaries
>>> d != False
1

Overrides: dict.__ne__

__gt__(self, other)
(Greater-than operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
>>> d > c
1
>>> c > d
0
>>> d > dict(c)
Traceback (most recent call last):
TypeError: Can only compare with other OrderedDicts

Overrides: dict.__gt__

__ge__(self, other)
(Greater-than-or-equals operator)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> c = OrderedDict(((0, 3), (3, 2), (2, 1)))
>>> e = OrderedDict(d)
>>> c >= d
0
>>> d >= c
1
>>> d >= dict(c)
Traceback (most recent call last):
TypeError: Can only compare with other OrderedDicts
>>> e >= d
1

Overrides: dict.__ge__

__repr__(self)
(Representation operator)

source code 

Used for __repr__ and __str__

>>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
>>> r1
"OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])"
>>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
>>> r2
"OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])"
>>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
1
>>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
1

Overrides: object.__repr__

__setitem__(self, key, val)
(Index assignment operator)

source code 

Allows slice assignment, so long as the slice is an OrderedDict
>>> d = OrderedDict()
>>> d['a'] = 'b'
>>> d['b'] = 'a'
>>> d[3] = 12
>>> d
OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)])
>>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4)))
>>> d
OrderedDict([(1, 2), (2, 3), (3, 4)])
>>> d[::2] = OrderedDict(((7, 8), (9, 10)))
>>> d
OrderedDict([(7, 8), (2, 3), (9, 10)])
>>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)))
>>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
>>> d
OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])
>>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True)
>>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8)))
>>> d
OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)])

>>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True)
>>> a[3] = 4
>>> a
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)])
Traceback (most recent call last):
ValueError: slice assignment must be from unique keys
>>> a = OrderedDict(((0, 1), (1, 2), (2, 3)))
>>> a[3] = 4
>>> a
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a
OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> a
OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)])

>>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> d[:1] = 3
Traceback (most recent call last):
TypeError: slice assignment requires an OrderedDict

>>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)])
>>> d[:1] = OrderedDict([(9, 8)])
>>> d
OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)])

Overrides: dict.__setitem__

__getitem__(self, key)
(Indexing operator)

source code 

Allows slicing. Returns an OrderedDict if you slice.
>>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)])
>>> b[::-1]
OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)])
>>> b[2:5]
OrderedDict([(5, 2), (4, 3), (3, 4)])
>>> type(b[2:4])
<class '__main__.OrderedDict'>

Overrides: dict.__getitem__

__str__(self)
(Informal representation operator)

source code 

Used for __repr__ and __str__

>>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
>>> r1
"OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])"
>>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
>>> r2
"OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])"
>>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f'))))
1
>>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd'))))
1

Overrides: object.__str__

__setattr__(self, name, value)

source code 

Implemented so that accesses to ``sequence`` raise a warning and are
diverted to the new ``setkeys`` method.

Overrides: object.__setattr__

__getattr__(self, name)
(Qualification operator)

source code 

Implemented so that access to ``sequence`` raises a warning.

>>> d = OrderedDict()
>>> d.sequence
[]

__deepcopy__(self, memo)

source code 

To allow deepcopy to work with OrderedDict.

>>> from copy import deepcopy
>>> a = OrderedDict([(1, 1), (2, 2), (3, 3)])
>>> a['test'] = {}
>>> b = deepcopy(a)
>>> b == a
1
>>> b is a
0
>>> a['test'] is b['test']
0

copy(self)

source code 

>>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy()
OrderedDict([(1, 3), (3, 2), (2, 1)])

Returns: a shallow copy of D
Overrides: dict.copy

items(self)

source code 

``items`` returns a list of tuples representing all the 
``(key, value)`` pairs in the dictionary.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.items()
[(1, 3), (3, 2), (2, 1)]
>>> d.clear()
>>> d.items()
[]

Returns: list of D's (key, value) pairs, as 2-tuples
Overrides: dict.items

keys(self)

source code 

Return a list of keys in the ``OrderedDict``.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.keys()
[1, 3, 2]

Returns: list of D's keys
Overrides: dict.keys

values(self, values=None)

source code 

Return a list of all the values in the OrderedDict.

Optionally you can pass in a list of values, which will replace the
current list. The value list must be the same len as the OrderedDict.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.values()
[3, 2, 1]

Returns: list of D's values
Overrides: dict.values

iteritems(self)

source code 

>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems()
>>> ii.next()
(1, 3)
>>> ii.next()
(3, 2)
>>> ii.next()
(2, 1)
>>> ii.next()
Traceback (most recent call last):
StopIteration

Returns: an iterator over the (key, value) items of D
Overrides: dict.iteritems

iterkeys(self)

source code 

>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()
>>> ii.next()
1
>>> ii.next()
3
>>> ii.next()
2
>>> ii.next()
Traceback (most recent call last):
StopIteration

Returns: an iterator over the keys of D
Overrides: dict.iterkeys

__iter__(self)

source code 

>>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys()
>>> ii.next()
1
>>> ii.next()
3
>>> ii.next()
2
>>> ii.next()
Traceback (most recent call last):
StopIteration

Returns: an iterator over the keys of D
Overrides: dict.__iter__

itervalues(self)

source code 

>>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues()
>>> iv.next()
3
>>> iv.next()
2
>>> iv.next()
1
>>> iv.next()
Traceback (most recent call last):
StopIteration

Returns: an iterator over the values of D
Overrides: dict.itervalues

clear(self)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.clear()
>>> d
OrderedDict([])

Returns: None
Overrides: dict.clear

pop(self, key, *args)

source code 

No dict.pop in Python 2.2, gotta reimplement it

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.pop(3)
2
>>> d
OrderedDict([(1, 3), (2, 1)])
>>> d.pop(4)
Traceback (most recent call last):
KeyError: 4
>>> d.pop(4, 0)
0
>>> d.pop(4, 0, 1)
Traceback (most recent call last):
TypeError: pop expected at most 2 arguments, got 3

Returns: v, remove specified key and return the corresponding value
Overrides: dict.pop

popitem(self, i=-1)

source code 

Delete and return an item specified by index, not a random one as in
dict. The index is -1 by default (the last item).

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.popitem()
(2, 1)
>>> d
OrderedDict([(1, 3), (3, 2)])
>>> d.popitem(0)
(1, 3)
>>> OrderedDict().popitem()
Traceback (most recent call last):
KeyError: 'popitem(): dictionary is empty'
>>> d.popitem(2)
Traceback (most recent call last):
IndexError: popitem(): index 2 not valid

Returns: (k, v), remove and return some (key, value) pair as a
Overrides: dict.popitem

setdefault(self, key, defval=None)

source code 

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.setdefault(1)
3
>>> d.setdefault(4) is None
1
>>> d
OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)])
>>> d.setdefault(5, 0)
0
>>> d
OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)])

Returns: D.get(k,d), also set D[k]=d if k not in D
Overrides: dict.setdefault

update(self, from_od)

source code 

Update from another OrderedDict or sequence of (key, value) pairs

>>> d = OrderedDict()
>>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1))))
>>> d
OrderedDict([(1, 3), (3, 2), (2, 1)])
>>> d.update({4: 4})
Traceback (most recent call last):
TypeError: undefined order, cannot get items from dict
>>> d.update((4, 4))
Traceback (most recent call last):
TypeError: cannot convert dictionary update sequence element #0 to a sequence

Returns: None
Overrides: dict.update

setitems(self, items)

source code 

This method allows you to set the items in the dict.

It takes a list of tuples - of the same sort returned by the ``items``
method.

>>> d = OrderedDict()
>>> d.setitems(((3, 1), (2, 3), (1, 2)))
>>> d
OrderedDict([(3, 1), (2, 3), (1, 2)])

setkeys(self, keys)

source code 

``setkeys`` all ows you to pass in a new list of keys which will
replace the current set. This must contain the same set of keys, but
need not be in the same order.

If you pass in new keys that don't match, a ``KeyError`` will be
raised.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.keys()
[1, 3, 2]
>>> d.setkeys((1, 2, 3))
>>> d
OrderedDict([(1, 3), (2, 1), (3, 2)])
>>> d.setkeys(['a', 'b', 'c'])
Traceback (most recent call last):
KeyError: 'Keylist is not the same as current keylist.'

setvalues(self, values)

source code 

You can pass in a list of values, which will replace the
current list. The value list must be the same len as the OrderedDict.

(Or a ``ValueError`` is raised.)

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.setvalues((1, 2, 3))
>>> d
OrderedDict([(1, 1), (3, 2), (2, 3)])
>>> d.setvalues([6])
Traceback (most recent call last):
ValueError: Value list is not the same length as the OrderedDict.

index(self, key)

source code 

Return the position of the specified key in the OrderedDict.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.index(3)
1
>>> d.index(4)
Traceback (most recent call last):
ValueError: list.index(x): x not in list

insert(self, index, key, value)

source code 

Takes ``index``, ``key``, and ``value`` as arguments.

Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in
the OrderedDict.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.insert(0, 4, 0)
>>> d
OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)])
>>> d.insert(0, 2, 1)
>>> d
OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)])
>>> d.insert(8, 8, 1)
>>> d
OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)])

reverse(self)

source code 

Reverse the order of the OrderedDict.

>>> d = OrderedDict(((1, 3), (3, 2), (2, 1)))
>>> d.reverse()
>>> d
OrderedDict([(2, 1), (3, 2), (1, 3)])

sort(self, *args, **kwargs)

source code 

Sort the key order in the OrderedDict.

This method takes the same arguments as the ``list.sort`` method on
your version of Python.

>>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4)))
>>> d.sort()
>>> d
OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)])