Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ R.equals(float('nan'), float('nan')) # True
- [x] 0.1.2 F
- [x] 0.1.2 filter
- [x] 0.1.2 find
- [ ] findIndex
- [ ] findLast
- [ ] findLastIndex
- [x] findIndex
- [x] findLast
- [x] findLastIndex
- [x] 0.1.2 flatten
- [x] 0.1.2 flip
- [x] forEach
Expand Down
3 changes: 3 additions & 0 deletions ramda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
from .F import F
from .filter import filter
from .find import find
from .findIndex import findIndex
from .findLast import findLast
from .findLastIndex import findLastIndex
from .flatten import flatten
from .flip import flip
from .forEach import forEach
Expand Down
16 changes: 16 additions & 0 deletions ramda/findIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .private._curry2 import _curry2
from .private._dispatchable import _dispatchable
from .private._xfindIndex import _xfindIndex


def inner_findIndex(fn, arr):
idx = 0
length = len(arr)
while idx < length:
if fn(arr[idx]):
return idx
idx += 1
return -1


findIndex = _curry2(_dispatchable([], _xfindIndex, inner_findIndex))
14 changes: 14 additions & 0 deletions ramda/findLast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .private._curry2 import _curry2
from .private._dispatchable import _dispatchable
from .private._xfindLast import _xfindLast


def inner_findLast(fn, arr):
idx = len(arr) - 1
while idx >= 0:
if fn(arr[idx]):
return arr[idx]
idx -= 1
return None

findLast = _curry2(_dispatchable([], _xfindLast, inner_findLast))
15 changes: 15 additions & 0 deletions ramda/findLastIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .private._curry2 import _curry2
from .private._dispatchable import _dispatchable
from .private._xfindLastIndex import _xfindLastIndex


def inner_findLastIndex(fn, arr):
idx = len(arr) - 1
while idx >= 0:
if fn(arr[idx]):
return idx
idx -= 1
return -1


findLastIndex = _curry2(_dispatchable([], _xfindLastIndex, inner_findLastIndex))
26 changes: 26 additions & 0 deletions ramda/private/_xfindIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from ._helper import getAttribute
from ._reduced import _reduced
from ._xfBase import XfBase


class XFindIndex(XfBase):
def __init__(self, f, xf):
self.xf = xf
self.f = f
self.idx = -1
self.found = False

def result(self, result):
if not self.found:
result = getAttribute(self.xf, '@@transducer/step')(result, -1)
return getAttribute(self.xf, '@@transducer/result')(result)

def step(self, result, _input):
self.idx += 1
if self.f(_input):
self.found = True
result = _reduced(getAttribute(self.xf, '@@transducer/step')(result, self.idx))
return result


def _xfindIndex(f): return lambda xf: XFindIndex(f, xf)
20 changes: 20 additions & 0 deletions ramda/private/_xfindLast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from ._helper import getAttribute
from ._xfBase import XfBase


class XFindLast(XfBase):
def __init__(self, f, xf):
self.xf = xf
self.f = f
self.last = None

def result(self, result):
return getAttribute(self.xf, '@@transducer/result')(getAttribute(self.xf, '@@transducer/step')(result, self.last))

def step(self, result, _input):
if self.f(_input):
self.last = _input
return result


def _xfindLast(f): return lambda xf: XFindLast(f, xf)
22 changes: 22 additions & 0 deletions ramda/private/_xfindLastIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ._helper import getAttribute
from ._xfBase import XfBase


class XFindLastIndex(XfBase):
def __init__(self, f, xf):
self.xf = xf
self.f = f
self.idx = -1
self.lastIdx = -1

def result(self, result):
return getAttribute(self.xf, '@@transducer/result')(getAttribute(self.xf, '@@transducer/step')(result, self.lastIdx))

def step(self, result, _input):
self.idx += 1
if self.f(_input):
self.lastIdx = self.idx
return result


def _xfindLastIndex(f): return lambda xf: XFindLastIndex(f, xf)
45 changes: 45 additions & 0 deletions test/test_findIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

import unittest

import ramda as R

from .helpers.listXf import listXf

"""
https://github.com/ramda/ramda/blob/master/test/findIndex.js
"""

obj1 = {'x': 100}
obj2 = {'x': 200}
a = [11, 10, 9, 'cow', obj1, 8, 7, 100, 200, 300, obj2, 4, 3, 2, 1, 0]
def even(x): return x % 2 == 0 if isinstance(x, int) else False
def gt100(x): return x > 100 if isinstance(x, int) else False
def isStr(x): return isinstance(x, str)
def xGt100(o): return o['x'] > 100 if isinstance(o, dict) and isinstance(o['x'], int) else False


class TestFindIndex(unittest.TestCase):
def test_returns_the_index_of_the_first_element_that_satisfies_the_predicate(self):
self.assertEqual(1, R.findIndex(even, a))
self.assertEqual(8, R.findIndex(gt100, a))
self.assertEqual(3, R.findIndex(isStr, a))
self.assertEqual(10, R.findIndex(xGt100, a))

def test_return_minus_one_when_no_element_satisfies_the_predicate(self):
self.assertEqual(-1, R.findIndex(even, ['zing']))
self.assertEqual(-1, R.findIndex(even, []))

def test_dispatches_to_transformer_objects(self):
res = R.findIndex(R.identity, listXf)
self.assertEqual(R.identity, res.f)
self.assertEqual(False, res.found)
self.assertEqual(-1, res.idx)
self.assertEqual(listXf, res.xf)

def test_can_act_as_a_transducer(self):
self.assertEqual([1], R.into([], R.findIndex(even), a))
# TODO: transducer tests


if __name__ == '__main__':
unittest.main()
46 changes: 46 additions & 0 deletions test/test_findLast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

import unittest

import ramda as R

from .helpers.listXf import listXf

"""
https://github.com/ramda/ramda/blob/master/test/findLast.js
"""

obj1 = {'x': 100}
obj2 = {'x': 200}
a = [11, 10, 9, 'cow', obj1, 8, 7, 100, 200, 300, obj2, 4, 3, 2, 1, 0]
def even(x): return x % 2 == 0 if isinstance(x, int) else False
def gt100(x): return x > 100 if isinstance(x, int) else False
def isStr(x): return isinstance(x, str)
def xGt100(o): return o['x'] > 100 if isinstance(o, dict) and isinstance(o['x'], int) else False


class TestFindLast(unittest.TestCase):
def test_returns_the_index_of_the_last_element_that_satisfies_the_predicate(self):
self.assertEqual(0, R.findLast(even, a))
self.assertEqual(300, R.findLast(gt100, a))
self.assertEqual('cow', R.findLast(isStr, a))
self.assertEqual(obj2, R.findLast(xGt100, a))

def test_return_None_when_no_element_satisfies_the_predicate(self):
self.assertEqual(None, R.findLast(even, ['zing']))
self.assertEqual(None, R.findLast(even, []))

def test_works_when_the_first_element_matches(self):
self.assertEqual(2, R.findLast(even, [2, 3, 5]))

def test_dispatches_to_transformer_objects(self):
res = R.findLast(R.identity, listXf)
self.assertEqual(R.identity, res.f)
self.assertEqual(listXf, res.xf)

def test_can_act_as_a_transducer(self):
self.assertEqual([0], R.into([], R.findLast(even), a))
# TODO: transducer tests


if __name__ == '__main__':
unittest.main()
49 changes: 49 additions & 0 deletions test/test_findLastIndex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

import unittest

import ramda as R

from .helpers.listXf import listXf

"""
https://github.com/ramda/ramda/blob/master/test/findLastIndex.js
"""

obj1 = {'x': 100}
obj2 = {'x': 200}
a = [11, 10, 9, 'cow', obj1, 8, 7, 100, 200, 300, obj2, 4, 3, 2, 1, 0]
def even(x): return x % 2 == 0 if isinstance(x, int) else False
def gt100(x): return x > 100 if isinstance(x, int) else False
def isStr(x): return isinstance(x, str)
def xGt100(o): return o['x'] > 100 if isinstance(o, dict) and isinstance(o['x'], int) else False


class TestfindLastIndex(unittest.TestCase):
def test_returns_the_index_of_the_last_element_that_satisfies_the_predicate(self):
self.assertEqual(15, R.findLastIndex(even, a))
self.assertEqual(9, R.findLastIndex(gt100, a))
self.assertEqual(3, R.findLastIndex(isStr, a))
self.assertEqual(10, R.findLastIndex(xGt100, a))

def test_return_minus_one_when_no_element_satisfies_the_predicate(self):
self.assertEqual(-1, R.findLastIndex(even, ['zing']))
self.assertEqual(-1, R.findLastIndex(even, []))

def test_works_when_the_first_element_matches(self):
self.assertEqual(0, R.findLastIndex(even, [2, 3, 5]))
self.assertEqual(3, R.findLastIndex(even, [2, 3, 5, 6]))

def test_dispatches_to_transformer_objects(self):
res = R.findLastIndex(R.identity, listXf)
self.assertEqual(R.identity, res.f)
self.assertEqual(-1, res.idx)
self.assertEqual(-1, res.lastIdx)
self.assertEqual(listXf, res.xf)

def test_can_act_as_a_transducer(self):
self.assertEqual([15], R.into([], R.findLastIndex(even), a))
# TODO: transducer tests


if __name__ == '__main__':
unittest.main()