Skip to content

Commit 0845a12

Browse files
authored
Merge pull request #19 from kthyng/add
Added merge and iadd
2 parents 39ab8fe + 3281df4 commit 0845a12

File tree

4 files changed

+82
-12
lines changed

4 files changed

+82
-12
lines changed

cf_pandas/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .options import set_options # noqa
99
from .reg import Reg
1010
from .utils import always_iterable, astype, match_criteria_key, standard_names
11-
from .vocab import Vocab
11+
from .vocab import Vocab, merge
1212
from .widget import Selector, dropdown
1313

1414

cf_pandas/vocab.py

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pathlib
55

66
from collections import defaultdict
7-
from typing import DefaultDict, Dict, Optional, Union
7+
from typing import DefaultDict, Dict, Optional, Sequence, Union
88

99
from .utils import astype
1010

@@ -51,22 +51,37 @@ def make_entry(
5151
expressions = astype(expressions, list)
5252
entry: DefaultDict[str, Dict[str, str]] = defaultdict(dict)
5353
entry[nickname][attr] = "|".join(expressions)
54-
self.__add__(entry)
54+
self.__iadd__(entry)
5555

56-
def __add__(self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"]):
56+
def add(
57+
self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"], method: str
58+
) -> "Vocab":
5759
"""Add two Vocab objects together...
5860
5961
by adding their `.vocab`s together. Expressions are piped together but otherwise not changed.
62+
This is used for both `__add__` and `__iadd__`.
6063
6164
Parameters
6265
----------
6366
other_vocab: Vocab
6467
Other Vocab object to combine with.
68+
method : str
69+
Whether to run as "add" which returns a new Vocab object or "iadd" which adds to the original object.
70+
71+
Returns
72+
-------
73+
Vocab
74+
vocab + other_vocab either as a new object or in place.
6575
"""
6676

6777
if isinstance(other_vocab, Vocab):
6878
other_vocab = other_vocab.vocab
6979

80+
if method == "add":
81+
output = Vocab()
82+
elif method == "iadd":
83+
output = self
84+
7085
nicknames = set(list(self.vocab.keys()) + list(other_vocab.keys()))
7186
for nickname in nicknames:
7287

@@ -82,8 +97,22 @@ def __add__(self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"])
8297
+ "|"
8398
+ other_vocab[nickname].get(attribute, "")
8499
).strip("|")
85-
self.vocab[nickname][attribute] = new_expressions
86-
return self
100+
output.vocab[nickname][attribute] = new_expressions
101+
return output
102+
103+
def __add__(self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"]):
104+
"""vocab1 + vocab2"""
105+
return self.add(other_vocab, "add")
106+
107+
def __iadd__(self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"]):
108+
"""vocab1 += vocab2"""
109+
return self.add(other_vocab, "iadd")
110+
111+
def __radd__(
112+
self, other_vocab: Union[DefaultDict[str, Dict[str, str]], "Vocab"]
113+
) -> "Vocab":
114+
"""right add?"""
115+
return self.__add__(other_vocab)
87116

88117
def save(self, savename: Union[str, pathlib.PurePath]):
89118
"""Save to file.
@@ -108,3 +137,23 @@ def open_file(self, openname: Union[str, pathlib.PurePath]):
108137
return json.loads(
109138
open(pathlib.PurePath(openname).with_suffix(".json"), "r").read()
110139
)
140+
141+
142+
def merge(vocabs: Sequence[Vocab]) -> Vocab:
143+
"""Add together multiple Vocab objects.
144+
145+
Parameters
146+
----------
147+
vocabs : Sequence[Vocab]
148+
Sequence of Vocab objects to merge.
149+
150+
Returns
151+
-------
152+
Vocab
153+
Single Vocab object made up of input vocabs.
154+
"""
155+
156+
final_vocab = Vocab()
157+
for vocab in vocabs:
158+
final_vocab += vocab
159+
return final_vocab

docs/demo_vocab.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jupytext:
66
format_version: 0.13
77
jupytext_version: 1.14.0
88
kernelspec:
9-
display_name: Python 3 (ipykernel)
9+
display_name: Python 3.10.6 ('cf-pandas')
1010
language: python
1111
name: python3
1212
---
@@ -139,6 +139,19 @@ vocab2.make_entry("other_variable_nickname", "match_that_string", attr="standard
139139
vocab1 + vocab2
140140
```
141141

142+
Merge 2 or more Vocab objects:
143+
144+
```{code-cell} ipython3
145+
cfp.merge([vocab1, vocab2])
146+
```
147+
148+
Can also add in place
149+
150+
```{code-cell} ipython3
151+
# also works
152+
vocab1 += vocab2
153+
```
154+
142155
## Use the `Reg` class to write regular expressions
143156

144157
We used simple exact matching regular expressions above, but for anything more complicated it can be hard to write regular expressions. You can use the `Reg` class in `cf-pandas` to write regular expressions with several options, as demonstrated more in [another doc page](https://cf-pandas.readthedocs.io/en/latest/demo_reg.html), and briefly here.

tests/test_vocab.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,27 @@ def test_make_entry():
2020

2121
def test_add_vocabs():
2222
vocab = cfp.Vocab()
23-
vocab.make_entry("temp", ["a", "b"], attr="standard_name")
24-
vocab.make_entry("salt", ["a", "b"], attr="name")
23+
vocab.vocab = defaultdict(
24+
dict, {"temp": {"standard_name": "a|b"}, "salt": {"name": "a|b"}}
25+
)
2526
compare = {"temp": {"standard_name": "a|b|a|b"}, "salt": {"name": "a|b|a|b"}}
2627
assert (vocab + vocab).vocab == compare
2728

2829
vocab2 = cfp.Vocab()
29-
vocab2.make_entry("temp", ["a", "b"], attr="name")
30+
vocab2.vocab = defaultdict(dict, {"temp": {"name": "a|b"}})
3031
compare = {
31-
"temp": {"name": "a|b", "standard_name": "a|b|a|b"},
32-
"salt": {"name": "a|b|a|b"},
32+
"temp": {"standard_name": "a|b", "name": "a|b"},
33+
"salt": {"name": "a|b"},
3334
}
3435
assert (vocab + vocab2).vocab == compare
3536

37+
# also merge
38+
assert cfp.merge([vocab, vocab2]).vocab == compare
39+
40+
# also iadd
41+
vocab += vocab2
42+
assert vocab.vocab == compare
43+
3644

3745
def test_make_more_entries():
3846
vocab = cfp.Vocab()

0 commit comments

Comments
 (0)