|
2 | 2 | import json as _json
|
3 | 3 | import sys
|
4 | 4 | import re
|
| 5 | +from functools import reduce |
5 | 6 |
|
6 | 7 | from _plotly_utils.optional_imports import get_module
|
7 | 8 | from _plotly_utils.basevalidators import ImageUriValidator
|
|
10 | 11 | PY36_OR_LATER = sys.version_info >= (3, 6)
|
11 | 12 |
|
12 | 13 |
|
| 14 | +def cumsum(x): |
| 15 | + """ |
| 16 | + Custom cumsum to avoid a numpy import. |
| 17 | + """ |
| 18 | + |
| 19 | + def _reducer(a, x): |
| 20 | + if len(a) == 0: |
| 21 | + return [x] |
| 22 | + return a + [a[-1] + x] |
| 23 | + |
| 24 | + ret = reduce(_reducer, x, []) |
| 25 | + return ret |
| 26 | + |
| 27 | + |
13 | 28 | class PlotlyJSONEncoder(_json.JSONEncoder):
|
14 | 29 | """
|
15 | 30 | Meant to be passed as the `cls` kwarg to json.dumps(obj, cls=..)
|
@@ -256,3 +271,76 @@ def _get_int_type():
|
256 | 271 | else:
|
257 | 272 | int_type = (int,)
|
258 | 273 | return int_type
|
| 274 | + |
| 275 | + |
| 276 | +def split_multichar(ss, chars): |
| 277 | + """ |
| 278 | + Split all the strings in ss at any of the characters in chars. |
| 279 | + Example: |
| 280 | +
|
| 281 | + >>> ss = ["a.string[0].with_separators"] |
| 282 | + >>> chars = list(".[]_") |
| 283 | + >>> split_multichar(ss, chars) |
| 284 | + ['a', 'string', '0', '', 'with', 'separators'] |
| 285 | +
|
| 286 | + :param (list) ss: A list of strings. |
| 287 | + :param (list) chars: Is a list of chars (note: not a string). |
| 288 | + """ |
| 289 | + if len(chars) == 0: |
| 290 | + return ss |
| 291 | + c = chars.pop() |
| 292 | + ss = reduce(lambda x, y: x + y, map(lambda x: x.split(c), ss)) |
| 293 | + return split_multichar(ss, chars) |
| 294 | + |
| 295 | + |
| 296 | +def split_string_positions(ss): |
| 297 | + """ |
| 298 | + Given a list of strings split using split_multichar, return a list of |
| 299 | + integers representing the indices of the first character of every string in |
| 300 | + the original string. |
| 301 | + Example: |
| 302 | +
|
| 303 | + >>> ss = ["a.string[0].with_separators"] |
| 304 | + >>> chars = list(".[]_") |
| 305 | + >>> ss_split = split_multichar(ss, chars) |
| 306 | + >>> ss_split |
| 307 | + ['a', 'string', '0', '', 'with', 'separators'] |
| 308 | + >>> split_string_positions(ss_split) |
| 309 | + [0, 2, 9, 11, 12, 17] |
| 310 | +
|
| 311 | + :param (list) ss: A list of strings. |
| 312 | + """ |
| 313 | + return list( |
| 314 | + map( |
| 315 | + lambda t: t[0] + t[1], |
| 316 | + zip(range(len(ss)), cumsum([0] + list(map(len, ss[:-1])))), |
| 317 | + ) |
| 318 | + ) |
| 319 | + |
| 320 | + |
| 321 | +def display_string_positions(p, i=None): |
| 322 | + """ |
| 323 | + Return a string that is whitespace except at p[i] which is replaced with ^. |
| 324 | + If i is None then all the indices of the string in p are replaced with ^. |
| 325 | + Example: |
| 326 | +
|
| 327 | + >>> ss = ["a.string[0].with_separators"] |
| 328 | + >>> chars = list(".[]_") |
| 329 | + >>> ss_split = split_multichar(ss, chars) |
| 330 | + >>> ss_split |
| 331 | + ['a', 'string', '0', '', 'with', 'separators'] |
| 332 | + >>> ss_pos = split_string_positions(ss_split) |
| 333 | + >>> ss[0] |
| 334 | + 'a.string[0].with_separators' |
| 335 | + >>> display_string_positions(ss_pos,4) |
| 336 | + ' ^' |
| 337 | + :param (list) p: A list of integers. |
| 338 | + :param (integer|None) i: Optional index of p to display. |
| 339 | + """ |
| 340 | + s = [" " for _ in range(max(p) + 1)] |
| 341 | + if i is None: |
| 342 | + for p_ in p: |
| 343 | + s[p_] = "^" |
| 344 | + else: |
| 345 | + s[p[i]] = "^" |
| 346 | + return "".join(s) |
0 commit comments