diff --git a/owrx/active/list/__init__.py b/owrx/active/list/__init__.py index a088f0f1..4c8c324d 100644 --- a/owrx/active/list/__init__.py +++ b/owrx/active/list/__init__.py @@ -48,6 +48,34 @@ class ActiveListTransformationListener(ActiveListListener): del self.target[change.index] +class ActiveListFilterListener(ActiveListListener): + def __init__(self, filter: callable, keyMap: list, target: "ActiveList"): + self.filter = filter + self.keyMap = keyMap + self.target = target + + def onListChange(self, changes: list[ActiveListChange]): + for change in changes: + if isinstance(change, ActiveListIndexAppended): + if self.filter(change.newValue): + self.target.append(change.newValue) + self.keyMap.append(len(self.target) - 1) + elif isinstance(change, ActiveListIndexUpdated): + if change.index in self.keyMap and not self.filter(change.newValue): + idx = self.keyMap.index(change.index) + del self.target[idx] + del self.keyMap[idx] + elif change.index not in self.keyMap and self.filter(change.newValue): + # TODO insert, not append + self.target.append(change.newValue) + self.keyMap.append(len(self.target) - 1) + elif isinstance(change, ActiveListIndexDeleted): + if change.index in self.keyMap: + idx = self.keyMap.index(change.index) + del self.target[idx] + del self.keyMap[idx] + + class ActiveList: def __init__(self, elements: list = None): self.delegate = elements.copy() if elements is not None else [] @@ -82,6 +110,16 @@ class ActiveList: self.addListener(ActiveListTransformationListener(transform, res)) return res + def filter(self, filter: callable): + res = ActiveList() + keyMap = [] + for idx, val in enumerate(self): + if filter(val): + res.append(val) + keyMap.append(idx) + self.addListener(ActiveListFilterListener(filter, keyMap, res)) + return res + def __setitem__(self, key, value): if self.delegate[key] == value: return diff --git a/test/owrx/active/list/test_active_list.py b/test/owrx/active/list/test_active_list.py index 1b658a18..2915713a 100644 --- a/test/owrx/active/list/test_active_list.py +++ b/test/owrx/active/list/test_active_list.py @@ -121,3 +121,30 @@ class ActiveListTest(TestCase): transformedList = list.map(lambda x: "prefix-{}".format(x)) del list[0] self.assertEqual(transformedList[0], "prefix-value2") + + def testFilter(self): + list = ActiveList([1, 2, 3, 4, 5]) + filteredList = list.filter(lambda x: x < 3) + self.assertEqual(len(filteredList), 2) + self.assertEqual(filteredList[0], 1) + self.assertEqual(filteredList[1], 2) + + def testActiveFilterAppend(self): + list = ActiveList([1, 2, 3, 4, 5]) + filteredList = list.filter(lambda x: x < 3) + list.append(0) + self.assertEqual(len(filteredList), 3) + self.assertEqual(filteredList[2], 0) + + def testActiveFilterUpdate(self): + list = ActiveList([1, 2, 3, 4, 5]) + filteredList = list.filter(lambda x: x < 3) + list[3] = 0 + self.assertEqual(len(filteredList), 3) + self.assertEqual(filteredList[2], 0) + + def testActiveFilterDelete(self): + list = ActiveList([1, 2, 3, 4, 5]) + filteredList = list.filter(lambda x: x < 3) + del list[1] + self.assertEqual(len(filteredList), 1)