diff options
author | Ross Barnowski <rossbar@berkeley.edu> | 2021-01-27 11:23:12 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-27 14:23:12 -0500 |
commit | b26480b1c236a581296c86c7c077600631d3babe (patch) | |
tree | 893bfbb9b1159538f4c4e89b6b94c639ebe3297c | |
parent | de9c66ff7790ae786c15c8b7bb5a05879fb454c7 (diff) | |
download | networkx-b26480b1c236a581296c86c7c077600631d3babe.tar.gz |
Update documentation and testing of arbitrary_element (#4451)
* Update documentation for arbitrary_element.
* Add numpydoc sections to docstring and extensive examples.
* Add to reference documentation.
* Add tests for arbitrary_element.
* Update networkx/utils/misc.py
Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
-rw-r--r-- | doc/reference/utils.rst | 1 | ||||
-rw-r--r-- | networkx/utils/misc.py | 69 | ||||
-rw-r--r-- | networkx/utils/tests/test_misc.py | 28 |
3 files changed, 84 insertions, 14 deletions
diff --git a/doc/reference/utils.rst b/doc/reference/utils.rst index 12e39395..636134ee 100644 --- a/doc/reference/utils.rst +++ b/doc/reference/utils.rst @@ -11,6 +11,7 @@ Helper Functions .. autosummary:: :toctree: generated/ + arbitrary_element is_string_like flatten iterable diff --git a/networkx/utils/misc.py b/networkx/utils/misc.py index e4beca5b..6d07bbd7 100644 --- a/networkx/utils/misc.py +++ b/networkx/utils/misc.py @@ -232,22 +232,63 @@ def arbitrary_element(iterable): """Returns an arbitrary element of `iterable` without removing it. This is most useful for "peeking" at an arbitrary element of a set, - but can be used for any list, dictionary, etc., as well:: + but can be used for any list, dictionary, etc., as well. - >>> arbitrary_element({3, 2, 1}) + Parameters + ---------- + iterable : `abc.collections.Iterable` instance + Any object that implements ``__iter__``, e.g. set, dict, list, tuple, + etc. + + Returns + ------- + The object that results from ``next(iter(iterable))`` + + Raises + ------ + ValueError + If `iterable` is an iterator (because the current implementation of + this function would consume an element from the iterator). + + Examples + -------- + Arbitrary elements from common Iterable objects: + + >>> arbitrary_element([1, 2, 3]) # list + 1 + >>> arbitrary_element((1, 2, 3)) # tuple + 1 + >>> arbitrary_element({1, 2, 3}) # set + 1 + >>> d = {k: v for k, v in zip([1, 2, 3], [3, 2, 1])} + >>> arbitrary_element(d) # dict_keys + 1 + >>> arbitrary_element(d.values()) # dict values + 3 + + `str` is also an Iterable: + + >>> arbitrary_element("hello") + 'h' + + :exc:`ValueError` is raised if `iterable` is an iterator: + + >>> iterator = iter([1, 2, 3]) # Iterator, *not* Iterable + >>> arbitrary_element(iterator) + Traceback (most recent call last): + ... + ValueError: cannot return an arbitrary item from an iterator + + Notes + ----- + This function does not return a *random* element. If `iterable` is + ordered, sequential calls will return the same value:: + + >>> l = [1, 2, 3] + >>> arbitrary_element(l) + 1 + >>> arbitrary_element(l) 1 - >>> arbitrary_element("hello") - 'h' - - This function raises a :exc:`ValueError` if `iterable` is an - iterator (because the current implementation of this function would - consume an element from the iterator):: - - >>> iterator = iter([1, 2, 3]) - >>> arbitrary_element(iterator) - Traceback (most recent call last): - ... - ValueError: cannot return an arbitrary item from an iterator """ if isinstance(iterable, Iterator): diff --git a/networkx/utils/tests/test_misc.py b/networkx/utils/tests/test_misc.py index 4abb7ce6..8f35d74b 100644 --- a/networkx/utils/tests/test_misc.py +++ b/networkx/utils/tests/test_misc.py @@ -4,6 +4,7 @@ import pytest import networkx as nx import random from networkx.utils import ( + arbitrary_element, create_py_random_state, create_random_state, discrete_sequence, @@ -271,3 +272,30 @@ def test_PythonRandomInterface(): ) assert rng.randint(3, 5) == rs42.randint(3, 6) assert rng.random() == rs42.random_sample() + + +@pytest.mark.parametrize( + ("iterable_type", "expected"), + ( + (list, 1), + (tuple, 1), + (str, "["), + (set, 1), + ), +) +def test_arbitrary_element(iterable_type, expected): + iterable = iterable_type([1, 2, 3]) + assert arbitrary_element(iterable) == expected + + +@pytest.mark.parametrize( + "iterator", + ( + (i for i in range(3)), # generator + iter([1, 2, 3]), + ), +) +def test_arbitrary_element_raises(iterator): + """Value error is raised when input is an iterator.""" + with pytest.raises(ValueError, match="from an iterator"): + arbitrary_element(iterator) |