-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfuncy.py
137 lines (99 loc) · 2.85 KB
/
funcy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import re
from collections import defaultdict
from operator import methodcaller
from itertools import tee, chain, islice
try:
from itertools import izip as zip
except ImportError:
pass
### funcy seqs
def first(seq):
return next(iter(seq), None)
def last(seq):
try:
return seq[-1]
except IndexError:
return None
except TypeError:
item = None
for item in seq:
pass
return item
def nth(n, seq):
"""Returns nth item in the sequence or None if no such item exists."""
try:
return seq[n]
except IndexError:
return None
except TypeError:
return next(islice(seq, n, None), None)
def remove(pred, seq):
return filter(complement(pred), seq)
def lremove(pred, seq):
return list(remove(pred, seq))
def without(seq, *items):
for value in seq:
if value not in items:
yield value
def lwithout(seq, *items):
return list(without(seq, *items))
def pairwise(seq):
a, b = tee(seq)
next(b, None)
return zip(a, b)
def with_next(seq, fill=None):
a, b = tee(seq)
next(b, None)
return zip(a, chain(b, [fill]))
def count_reps(seq):
"""Counts number occurrences of each value in the sequence."""
result = defaultdict(int)
for item in seq:
result[item] += 1
return result
### funcy strings
def _make_getter(regex):
if regex.groups == 0:
return methodcaller('group')
elif regex.groups == 1 and regex.groupindex == {}:
return methodcaller('group', 1)
elif regex.groupindex == {}:
return methodcaller('groups')
elif regex.groups == len(regex.groupindex):
return methodcaller('groupdict')
else:
return identity
_re_type = type(re.compile(r''))
def _prepare(regex, flags):
if not isinstance(regex, _re_type):
regex = re.compile(regex, flags)
return regex, _make_getter(regex)
def re_all(regex, s, flags=0):
return list(re_iter(regex, s, flags))
def re_find(regex, s, flags=0):
return re_finder(regex, flags)(s)
def re_test(regex, s, flags=0):
return re_tester(regex, flags)(s)
def re_finder(regex, flags=0):
regex, getter = _prepare(regex, flags)
return lambda s: iffy(getter)(regex.search(s))
def re_tester(regex, flags=0):
return lambda s: bool(re.search(regex, s, flags))
### funcy funcs
EMPTY = object()
def identity(x):
return x
def complement(func):
return lambda *a, **kw: not func(*a, **kw)
def iffy(pred, action=EMPTY, default=identity):
if action is EMPTY:
return iffy(bool, pred)
else:
return lambda v: action(v) if pred(v) else \
default(v) if callable(default) else \
default
### types tests
def isa(*types):
return lambda x: isinstance(x, types)
from collections import Iterable
iterable = isa(Iterable)