Skip to content

Commit 475fa44

Browse files
Nic-Mamonai-bot
andauthored
498 Add list to dict utility to parse variables (#904)
* [DLMED] add list_to_dict utility * [MONAI] python code formatting * [DLMED] update according to comments * [MONAI] python code formatting * [DLMED] add more tests Co-authored-by: monai-bot <[email protected]>
1 parent 0d197e6 commit 475fa44

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

monai/utils/misc.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import collections.abc
1313
import itertools
1414
import random
15+
from ast import literal_eval
16+
from distutils.util import strtobool
1517
from typing import Any, Callable, Optional, Sequence, Tuple, Union
1618

1719
import numpy as np
@@ -217,3 +219,37 @@ def set_determinism(
217219
torch.backends.cudnn.benchmark = False
218220
else:
219221
torch.backends.cudnn.deterministic = False
222+
223+
224+
def list_to_dict(items):
225+
"""
226+
To convert a list of "key=value" pairs into a dictionary.
227+
For examples: items: `["a=1", "b=2", "c=3"]`, return: {"a": "1", "b": "2", "c": "3"}.
228+
If no "=" in the pair, use None as the value, for example: ["a"], return: {"a": None}.
229+
Note that it will remove the blanks around keys and values.
230+
231+
"""
232+
233+
def _parse_var(s):
234+
items = s.split("=", maxsplit=1)
235+
key = items[0].strip(" \n\r\t'")
236+
value = None
237+
if len(items) > 1:
238+
value = items[1].strip(" \n\r\t'")
239+
return key, value
240+
241+
d = dict()
242+
if items:
243+
for item in items:
244+
key, value = _parse_var(item)
245+
246+
try:
247+
if key in d:
248+
raise KeyError(f"encounter duplicated key {key}.")
249+
d[key] = literal_eval(value)
250+
except ValueError:
251+
try:
252+
d[key] = bool(strtobool(str(value)))
253+
except ValueError:
254+
d[key] = value
255+
return d

tests/test_list_to_dict.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2020 MONAI Consortium
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
# Unless required by applicable law or agreed to in writing, software
7+
# distributed under the License is distributed on an "AS IS" BASIS,
8+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
# See the License for the specific language governing permissions and
10+
# limitations under the License.
11+
12+
import unittest
13+
14+
from parameterized import parameterized
15+
16+
from monai.utils import list_to_dict
17+
18+
TEST_CASE_1 = [
19+
["a=1", "b=2", "c=3", "d=4"],
20+
{"a": 1, "b": 2, "c": 3, "d": 4},
21+
]
22+
23+
TEST_CASE_2 = [
24+
["a=a", "b=b", "c=c", "d=d"],
25+
{"a": "a", "b": "b", "c": "c", "d": "d"},
26+
]
27+
28+
TEST_CASE_3 = [
29+
["a=0.1", "b=0.2", "c=0.3", "d=0.4"],
30+
{"a": 0.1, "b": 0.2, "c": 0.3, "d": 0.4},
31+
]
32+
33+
TEST_CASE_4 = [
34+
["a=True", "b=TRUE", "c=false", "d=FALSE"],
35+
{"a": True, "b": True, "c": False, "d": False},
36+
]
37+
38+
TEST_CASE_5 = [
39+
["a='1'", "b=2 ", " c = 3", "d='test'", "'e'=0", "f", "g=None"],
40+
{"a": 1, "b": 2, "c": 3, "d": "test", "e": 0, "f": None, "g": None},
41+
]
42+
43+
44+
class TestListToDict(unittest.TestCase):
45+
@parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_3, TEST_CASE_4, TEST_CASE_5])
46+
def test_value_shape(self, input, output):
47+
result = list_to_dict(input)
48+
self.assertDictEqual(result, output)
49+
50+
51+
if __name__ == "__main__":
52+
unittest.main()

0 commit comments

Comments
 (0)