Skip to content

Commit d518366

Browse files
committed
Added distinct_by transformation
1 parent 65a43f6 commit d518366

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

functional/chain.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,16 @@ def distinct(self):
10941094
"""
10951095
return self._transform(transformations.distinct_t())
10961096

1097+
def distinct_by(self, func):
1098+
"""
1099+
Returns sequence of elements who are distinct by the passed function. The return
1100+
value of func must be hashable. When two elements are distinct by func, the first is taken.
1101+
:param func: function to use for determining distinctness
1102+
:return: elements distinct by func
1103+
:rtype FunctionalSequence
1104+
"""
1105+
return self._transform(transformations.distinct_by_t(func))
1106+
10971107
def slice(self, start, until):
10981108
"""
10991109
Takes a slice of the sequence starting at start and until but not including until.

functional/transformations.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ def distinct(sequence):
5353
return Transformation('distinct', distinct, None)
5454

5555

56+
def distinct_by_t(func):
57+
def distinct_by(sequence):
58+
distinct_lookup = {}
59+
for element in sequence:
60+
key = func(element)
61+
if key not in distinct_lookup:
62+
distinct_lookup[key] = element
63+
return distinct_lookup.values()
64+
return Transformation('distinct_by({0})'.format(func.__name__), distinct_by, None)
65+
66+
5667
def sorted_t(key=None, reverse=False):
5768
return Transformation(
5869
'sorted',

test/test_functional.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import unittest
2+
from collections import namedtuple
23
from functional.chain import seq, FunctionalSequence, _wrap, is_iterable
34

45

6+
Data = namedtuple('Data', 'x y')
7+
58
class TestChain(unittest.TestCase):
69
def assert_type(self, s):
710
self.assertTrue(isinstance(s, FunctionalSequence))
@@ -324,6 +327,13 @@ def test_distinct(self):
324327
self.assertEqual(result.size(), len(expect))
325328
self.assert_type(result)
326329

330+
def test_distinct_by(self):
331+
s = seq(Data(1, 2), Data(1, 3), Data(2, 0), Data(3, -1), Data(1, 5))
332+
expect = {Data(1, 2), Data(2, 0), Data(3, -1)}
333+
result = s.distinct_by(lambda data: data.x)
334+
self.assertSetEqual(set(result), expect)
335+
self.assert_type(result)
336+
327337
def test_slice(self):
328338
s = seq([1, 2, 3, 4])
329339
result = s.slice(1, 2)

0 commit comments

Comments
 (0)