A library for list, dict, and UserDict manipulations.
Install arrayutilities via pip:
pip install arrayutilities- Installation
- Usage
- accessible
- add
- add_prefixed_keys_to
- add_unprefixed_keys_to
- collapse
- dot
- exists
- filter_prefixed
- first
- flatten
- forget
- get
- has
- insert_after_key
- insert_before_key
- is_dict
- is_list
- join
- last
- list_to_dict
- list_to_string
- merge_recursive
- only
- prepend
- pull
- query
- random
- recursive_ksort
- set
- shape_filter
- shuffle
- sort_by_priority
- sort_recursive
- sort_recursive_desc
- stringify_keys
- strpos
- str_to_list
- undot
- usearch
- visit_recursive
- where
- where_not_none
- wrap
Here are descriptions and usage examples for each method in the Arr class that you can get by:
from arrayutilities import Arr@staticmethod
def accessible(value)Determines if the given value is a list, dict, or UserDict.
Arguments:
valueAny - Value to determine if it is accessible.
Returns:
boolean- Whether the the value is a list, dict, or UserDict.
# With dicts!
my_dict = { 'a': 1 }
Arr.accessible(my_dict) # Result: True
# With lists!
my_list = [ 1 ]
Arr.accessible(my_list) # Result: True
# Other things aren't accessible.
Arr.accessible('bacon') # Result: False@staticmethod
def add(array, key, value)Add an element to an array if it doesn't exist.
Arguments:
array- Array to manipulate.key- Key to use.value- Value to inject.
Returns:
Manipulated array
# Add a key/value pair to a dict.
test_dict = {'a': 1}
result = Arr.add(test_dict, 'b', 2) # Result: {'a': 1, 'b': 2}
# Add a value to the end.
test_list = [1, 2, 3]
result = Arr.add(test_list, 4, 4) # Result: [1, 2, 3, 4]@staticmethod
def add_prefixed_keys_to(array, recursive=False)Duplicates any key not prefixed with '_' creating a prefixed duplicate one.
Arguments:
array- Array to manipulate.recursivebool, optional - Whether to recursively change the array. Defaults to False.
Returns:
Manipulated array.
# Prefix dicts.
my_dict = {'a': 1, 'b': 2}
result = Arr.add_prefixed_keys_to(my_dict) # Result: {'a': 1, 'b': 2, '_a': 1, '_b': 2}
# Prefix lists by converting to dicts.
my_list = [1, 2, 3]
result = Arr.add_prefixed_keys_to(my_list) # Result: {0: 1, 1: 2, 2: 3, '_0': 1, '_1': 2, '_2': 3}@staticmethod
def add_unprefixed_keys_to(array, recursive=False)Duplicates any key prefixed with '_' creating an un-prefixed duplicate one.
Arguments:
array- Array to manipulate.recursivebool, optional - Whether to recursively change the array. Defaults to False.
Returns:
Manipulated array.
# Unprefix dicts.
my_dict = {'_a': 1, '_b': 2}
result = Arr.add_unprefixed_keys_to(my_dict) # Result: {'_a': 1, '_b': 2, 'a': 1, 'b': 2}
# Recursively unprefix.
my_list = {'_a': {'_c': 3}, 'b': 2}
result = Arr.add_prefixed_keys_to(my_list) # Result: {'_a': {'_c': 3, 'c': 3}, 'b': 2, 'a': {'_c': 3, 'c': 3}}@staticmethod
def collapse(array)Collapse an array of arrays into a single array.
Arguments:
array- Array of arrays to collapse.
Returns:
Collapsed array.
Arr.collapse([[1, 2, 3]]) # Result: [1, 2, 3]
Arr.collapse([[1, 2], [3, 4], [5]]) # Result: [1, 2, 3, 4, 5]
Arr.collapse([[1, 'a'], [3.5, 4], [True, None]]) # Result: [1, 'a', 3.5, 4, True, None]
Arr.collapse([[], [1, 2], [], [3, 4], []]) # Result: [1, 2, 3, 4]@staticmethod
def dot(array, prepend='')Flatten a multi-dimensional associative array with dots.
Arguments:
array- Array to manipulate.prependstr, optional - Value to prepend to dict keys. Defaults to ''.
Returns:
Manipulated array.
Arr.dot({'a': 1, 'b': {'c': 2, 'd': {'e': 3}}}) # Result: {'a': 1, 'b.c': 2, 'b.d.e': 3}
Arr.dot({'a': 1}, 'init.') # Result: {'init.a': 1}@staticmethod
def exists(array, key)Determine if the given key exists in the provided array.
Arguments:
array- Array to check.key- Key to look for.
Returns:
boolean- Whether or not the key exists.
Arr.exists({'a': 1, '1.5': 'yup'}, 'a') # Result: True
Arr.exists({'a': 1, 'b': 2}, 'c') # Result: False@staticmethod
def filter_prefixed(array, prefix)Filters an associative array non-recursively, keeping only the values attached to keys starting with the specified prefix.
Arguments:
array- Array to filter.prefixstr|list - The prefix or prefixes of the keys to keep.
Returns:
Filtered array.
test_dict = {'pref_one': 1, 'pref_two': 2, 'nopref_three': 3}
Arr.filter_prefixed(test_dict, 'pref_') # Result: {'pref_one': 1, 'pref_two': 2}
test_dict = {'one': 1, 'two': 2, 'three': 3}
Arr.filter_prefixed(test_dict, 'pref_') # Result: {}@staticmethod
def first(array, callback=None, default=None)Return the first element in an array passing a given truth test.
Arguments:
array- Array to look at.callbackCallable, optional - Callback function that returns a boolean of whether to match or not. Defaults to None.defaultoptional - Default value if no other value is found. Defaults to None.
Returns:
Found value or default.
Arr.first({'a': 1, 'b': 2, 'c': 3}) # Result: 1
# Find the first element that matches a callback.
test_dict = {'a': 1, 'b': 2, 'c': 3}
Arr.first(test_dict, callback=lambda v, k: k == 'b') # Result: 2
# Find the first element that matches a callback or return a default value.
test_dict = {'a': 1, 'b': 2, 'c': 3}
result = Arr.first(test_dict, callback=lambda v, k: k == 'z', default=None) # Result: None@staticmethod
def flatten(array, depth=float('inf'))Flatten a multi-dimensional array into a single level.
Arguments:
array- Array to flatten.depthnumber, optional - Number of nestings deep that should be flattened. Defaults to float('inf').
Returns:
Flattened array.
test_array = [1, [2, 3], 4]
Arr.flatten(test_array) # Result: [1, 2, 3, 4]
test_array = [1, [2, [3, [4, 5]]], 6]
Arr.flatten(test_array, depth=2) # Result: [1, 2, 3, [4, 5], 6]@staticmethod
def forget(array, keys)Remove one or many array items from a given array using "dot" notation.
Arguments:
array- Array to manipulate.keysstr|array - Key or keys to remove.
test_dict = {'a': 1, 'b': 2, 'c': 3}
Arr.forget(test_dict, 'b') # Dict is now: {'a': 1, 'c': 3}
test_dict = {'a': 1, 'b': 2, 'c': {'d': 3, 'e': 4}}
Arr.forget(test_dict, ['a', 'c.d']) # Dict is now: {'b': 2, 'c': {'e': 4}}@staticmethod
def get(array, keys, default=None)Find a value inside of an array or object, including one nested a few levels deep.
Arguments:
array- Array to searchkeysstr|array - Key or keys to get.defaultoptional - Value to return if none found. Defaults to None.
Returns:
_type_- description
test_dict = {'a': 1, 'b': 2, 'c': 3}
Arr.get(test_dict, 'b') # Result: 2
test_dict = {'a': 1, 'b': {'c': { 'e': 2}, 'd': 3}}
Arr.get(test_dict, ['c', 'e']) # Result: 2@staticmethod
def has(array, keys)Check if an item or items exist in an array using "dot" notation.
Arguments:
array- Array to check.keysstr|array - The indexes to search; in order the function will look from the first to the last.
Returns:
boolean- Whether the key exists or not.
Arr.has({'a': 1, 'b': 2}, 'a') # Result: True
Arr.has({'a': 1, 'b': 2, 'c': 3}, ['a', 'b']) # Result: True
Arr.has({'a': 1, 'b': 2}, ['a', 'x']) # Result: False@staticmethod
def insert_after_key(key, source_array, insert)Insert an array after a specified key within another array.
Arguments:
keystr|number - The key of the array to insert after.source_arrayarray - The array to insert into.insertAny - Value or array to insert.
Returns:
Manipulated array.
Arr.insert_after_key(2, [1, 2, 3, 4], 5) # Result: [1, 2, 3, 5, 4]
Arr.insert_after_key('b', {'a': 1, 'b': 2, 'c': 3}, {'new': 25}) # Result: {'a': 1, 'b': 2, 'new': 25, 'c': 3}
Arr.insert_after_key('b', {'a': 1, 'b': 2, 'c': 3}, 25) # Result: raises TypeError@staticmethod
def insert_before_key(key, source_array, insert)Insert an array before a specified key within another array.
Arguments:
keystr|number - The key of the array to insert before.source_arrayarray - The array to insert into.insertAny - Value or array to insert.
Returns:
Manipulated array.
Arr.insert_before_key(1, [10, 20, 30], 15) # Result: [10, 15, 20, 30]
Arr.insert_before_key('b', {'a': 1, 'b': 2, 'c': 3}, {'new': 25}) # Result: {'a': 1, 'new': 25, 'b': 2, 'c': 3}
Arr.insert_before_key('b', {'a': 1, 'b': 2, 'c': 3}, 25) # Result: raises TypeError@staticmethod
def is_dict(array)Returns whether the array is a dict or not.
Arguments:
arrayarray - Array to check.
Returns:
boolean- Whether the array is a dict or not.
Arr.is_dict({}) # Result: True
Arr.is_dict([]) # Result: False
Arr.is_dict(1) # Result: False@staticmethod
def is_list(array)Returns whether the array is a list or not.
Arguments:
arrayarray - Array to check.
Returns:
boolean- Whether the array is a list or not.
Arr.is_list([]) # Result: True
Arr.is_list({}) # Result: False
Arr.is_list(1) # Result: False@staticmethod
def join(array, glue, final_glue='')Join all items using a string. The final items can use a separate glue string.
Arguments:
array- Array to join.gluestr - String to inject between elements.final_gluestr, optional - String to inject between the final two elements. Defaults to ''.
Returns:
str- Joined string.
Arr.join(['apple', 'banana', 'cherry'], ', ') # Result: 'apple, banana, cherry'
Arr.join(['apple', 'banana', 'cherry'], ', ', ', and ') # Result: 'apple, banana, and cherry'@staticmethod
def last(array, callback=None, default=None)Return the last element in an array passing a given truth test.
Arguments:
array- Array to look at.callbackCallable, optional - Callback function that returns a boolean of whether to match or not. Defaults to None.defaultoptional - Default value if no other value is found. Defaults to None.
Returns:
Found value or default.
Arr.last([1, 2, 3]) # Result: 3
Arr.last([1, 2, 3, 4, 5], lambda x: x % 2 == 0) # Result: 4
Arr.last([1, 3, 5], lambda x: x % 2 == 0, default='no match') # Result: 'no match'@staticmethod
def list_to_dict(value)Converts a list to a dict.
Arguments:
valuelist - A list to convert to a dict.
Returns:
Manipulated array.
Arr.list_to_dict([]) # Result: {}
Arr.list_to_dict(['apple', 'banana', 'cherry']) # Result: {0: 'apple', 1: 'banana', 2: 'cherry'}
Arr.list_to_dict('not a list') # Result: {0: 'not a list'}@staticmethod
def list_to_string(list_items, sep=',')Returns a list separated by the specified separator.
Arguments:
list_items- Array of items.sepstr, optional - Separator. Defaults to ','.
Returns:
The list separated by the specified separator or the original list if the list is empty.
Arr.list_to_string(['apple', 'banana', 'cherry']) # Result: 'apple,banana,cherry'
Arr.list_to_string(['apple', 'banana', 'cherry'], sep=';') # Result: 'apple;banana;cherry'@staticmethod
def merge_recursive(array1, array2)Recursively merge two arrays preserving keys.
Arguments:
array1- Starting array.array2- Array to merge into the first.
Returns:
Merged array.
array1 = {'a': 1, 'b': 2}
array2 = {'b': 3, 'c': 4}
Arr.merge_recursive(array1, array2) # Result: {'a': 1, 'b': 3, 'c': 4}
array1 = {'a': {'b': 1, 'c': 2}}
array2 = {'a': {'c': 3, 'd': 4}}
Arr.merge_recursive(array1, array2) # Result: {'a': {'b': 1, 'c': 3, 'd': 4}}@staticmethod
def only(array, keys)Get a subset of the items from the given array.
Arguments:
array- Array to search.keysstr|array - Key or keys to include in the final array.
Returns:
Array subset.
array = {'a': 1, 'b': 2, 'c': 3}
keys = ['a', 'c']
Arr.only(array, keys) # Result: {'a': 1, 'c': 3}
array = {'a': 1, 'b': 2, 'c': 3}
keys = ['x', 'y', 'z']
Arr.only(array, keys) # Result: {}@staticmethod
def prepend(array, value, key=None)Push an item onto the beginning of an array.
Arguments:
array- Array to manipulate.valueAny - Value to prepend.keystring|number, optional - Key value for the prepended item. Defaults to None.
Returns:
Manipulated array.
Arr.prepend([2, 3, 4], 10) # Result: [10, 2, 3, 4]
Arr.prepend({'b': 2, 'c': 3}, 10) # Result: {0: 10, 'b': 2, 'c': 3}
Arr.prepend({'b': 2, 'c': 3}, 10, 'a') # Result: {'a': 10, 'b': 2, 'c': 3}@staticmethod
def pull(array, key, default=None)Get a value from the array, and remove it.
Arguments:
array- Array to search and manipulate.keystr|number - Key to look for and fetch.defaultAny, optional - Default value if none found. Defaults to None.
Returns:
Any- The found value or default.
array = {'a': 1, 'b': 2, 'c': 3}
key = 'b'
Arr.pull(array, key) # Result: 2, Dictionary is now: {'a': 1, 'c': 3}
array = {'a': 1, 'b': 2, 'c': 3}
key = 'd'
default = 'not found'
result = Arr.pull(array, key, default) # Result: 'not found', Dictionary is now: {'a': 1, 'b': 2, 'c': 3}@staticmethod
def query(data)Convert the array into a query string.
Arguments:
data- Array to convert.
Returns:
str- URL query string.
data = {'name': 'John', 'age': 30, 'city': 'New York'}
Arr.query(data) # Result: 'name=John&age=30&city=New+York'
data = {'name': 'John', 'info': {'age': 30, 'city': 'New York'}}
Arr.query(data) # Result: 'name=John&info[age]=30&info[city]=New+York'
data = {'name': 'John', 'info': {'age': 30, 'city': ['New York', 'Phoenix']}}
Arr.query(data) # Result: 'name=John&info[age]=30&info[city][0]=New+York&info[city][1]=Phoenix'@staticmethod
def random(array, number=None, preserve_keys=False)Get one or a specified number of random values from an array.
Arguments:
array- Array to search through.numbernumber, optional - Number of items to randomly grab. Defaults to None.preserve_keysbool, optional - Whether the keys should be preserved or not. Defaults to False.
Raises:
ValueError
Returns:
Array with the random values.
Arr.random({'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}) # Result: 1 random value
Arr.random({'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}, number=3, preserve_keys=True) # Result: 3 random values with keys@staticmethod
def recursive_ksort(array)Recursively key-sort an array.
Arguments:
array- The array to sort.
Returns:
Sorted array.
test_dict = {'b': 2, 'a': 1}
Arr.recursive_ksort(test_dict) # Result: {'a': 1, 'b': 2}
test_dict = {'b': 2, 'a': {'c': 3, 'b': 2}, 'd': [4, 3, 2], 'c': 'hello'}
Arr.recursive_ksort(test_dict) # Result: {'a': {'b': 2, 'c': 3}, 'b': 2, 'c': 'hello', 'd': [4, 3, 2]}@staticmethod
def set(array, keys, value)Set key/value within an array, can set a key nested inside of a multidimensional array.
Arguments:
array- The array containing the key this sets.keysarray - To set a key nested multiple levels deep pass an array specifying each key in order as a value.Example- array( 'lvl1', 'lvl2', 'lvl3' );valueAny - The value.
Returns:
The manipulated array.
Arr.set({}, 'a', 1) # Result: {'a': 1}
Arr.set({}, ['a', 'b', 'c'], 1) # Result: {'a': {'b': {'c': 1}}}@staticmethod
def shape_filter(array, shape)Shapes, filtering it, an array to the specified expected set of required keys.
Arguments:
array- The input array to shape.shapearray - The shape to update the array with. It should only define keys or arrays of keys. Keys that have no values will be set to null. To add the key only if set, prefix the key with ?, e.g. ?foo.
Returns:
The manipulated array.
test_dict = {'a': 1, 'b': 2, 'c': 3}
shape = {'a': None, 'b': None}
Arr.shape_filter(test_dict, shape) # Result: {'a': 1, 'b': 2}
test_dict = {'a': {'b': 1, 'c': 2}, 'd': {'e': 3, 'f': 4}}
shape = {'a': {'b': None}}
Arr.shape_filter(test_dict, shape) # Result: {'a': {'b': 1}}
test_dict = {'a': 1, 'b': 2}
shape = {'a': None, 'c': None}
Arr.shape_filter(test_dict, shape) # Result: {'a': 1}@staticmethod
def shuffle(array, seed=None)Shuffle the given array and return the result.
Arguments:
array- Array to shuffle.seedAny, optional - The random number generator seed. Defaults to None.
Returns:
The shuffled array.
test_array = [i for i in range(1, 25)]
Arr.shuffle(test_array) # Result: Shuffled array
test_array = [i for i in range(1, 25)]
Arr.shuffle(test_array, 1234) # Result: Shuffled array with a specific seed@staticmethod
def sort_by_priority(array)Sort based on Priority.
Arguments:
array- A dict with priority keys.
Returns:
Sorted dict.
input_array = [{'name': 'John', 'priority': 2}, {'name': 'Alice', 'priority': 1}, {'name': 'Bob', 'priority': 3}]
Arr.sort_by_priority(input_array) # Result: [{'name': 'Alice', 'priority': 1}, {'name': 'John', 'priority': 2}, {'name': 'Bob', 'priority': 3}]@staticmethod
def sort_recursive(array, descending=False)Recursively sort an array by keys and values.
Arguments:
array- Array to sortdescendingbool, optional - Whether to sort in descending order or not. Defaults to False.
Returns:
Sorted array.
input_array = {'c': 3, 'a': {'b': 2, 'd': 4}}
Arr.sort_recursive(input_array) # Result: {'a': {'b': 2, 'd': 4}, 'c': 3}
input_array = {'c': 3, 'a': {'b': 2, 'd': 4}}
Arr.sort_recursive(input_array, descending=True) # Result: {'c': 3, 'a': {'d': 4, 'b': 2}}@staticmethod
def sort_recursive_desc(array)Recursively sort an array by keys and values in descending order.
Arguments:
array- Array to sort
Returns:
Sorted array.
input_array = {'c': 3, 'a': {'b': 2, 'd': 4}}
Arr.sort_recursive_desc(input_array) # Result: {'c': 3, 'a': {'d': 4, 'b': 2}}@staticmethod
def stringify_keys(input_array, prefix=None)Stringifies the numeric keys of an array.
Arguments:
input_array- Array to manipulate.prefixstr, optional - Prefix for array keys. Defaults to None.
Returns:
Manipulated array.
test_array = {'a': 1, 'b': 2, 'c': 3}
prefix = 'prefix_'
result = Arr.stringify_keys(test_array, prefix) # Result: {'prefix_a': 1, 'prefix_b': 2, 'prefix_c': 3}
test_array = {1: 'a', 2: 'b', 3: 'c'}
result = Arr.stringify_keys(test_array, 'sk_') # Result: {'sk_1': 'a', 'sk_2': 'b', 'sk_3': 'c'}@staticmethod
def strpos(haystack, needles, offset=0)Behaves exactly like the native PHP's strpos(), but accepts an array of needles.
Arguments:
haystackstr - String to search through.needlesstr|array - Needle or needles to look for in the haystack.offsetint, optional - Starting position of search. Defaults to 0.
Returns:
_type_- description
Arr.strpos("hello world", "world") # Result: 6
Arr.strpos("hello world", "earth") # Result: False
Arr.strpos("hello world", ["world", "ello"]) # Result: 1
# Offset of 6.
Arr.strpos("hello world hello", "hello", 6) # Result: 12@staticmethod
def str_to_list(value, sep=',')Converts a list to an array filtering out empty string elements.
Arguments:
valuestr|number|None - A string representing a list of values separated by the specified separator or an array. If the list is a string (e.g. a CSV list) then it will urldecoded before processing.sepstr, optional - The char(s) separating the list elements; will be ignored if the list is an array. Defaults to ','.
Returns:
Manipulated array.
Arr.str_to_list("apple, banana, cherry") # Result: ["apple", "banana", "cherry"]
Arr.str_to_list("apple|banana|cherry", sep="|") # Result: ["apple", "banana", "cherry"]
Arr.str_to_list(" apple , banana , cherry ") # Result: ["apple", "banana", "cherry"]
Arr.str_to_list(" ") # Result: []@staticmethod
def undot(obj)Convert a flatten "dot" notation array into an expanded array.
Arguments:
obj- Array to undot.
Returns:
Manipulated array.
Arr.undot({'a.b': 1, 'a.c.d': 2, 'e.f.g': 3}) # Result: {'a': {'b': 1, 'c': {'d': 2}}, 'e': {'f': {'g': 3}}}
# Duplicate keys. The last one takes precedence.
Arr.undot({'a.b': 1, 'a.b.c': 2, 'a.b.c.d': 3}) # Result: {'a': {'b': {'c': {'d': 3}}}}@staticmethod
def usearch(needle, haystack, callback)Searches an array using a callback and returns the index of the first match.
Arguments:
needleAny - The element to search in the array.haystack- The array to search.callbackfunction - A callback function with signature def x(needle, value, key) :bool that will be used to find the first match of needle in haystack.
Returns:
Either the index of the first match or False if no match was found.
def callback(needle, value, key):
return needle == value
haystack = {'a': 1, 'b': 2, 'c': 3}
needle = 2
Arr.usearch(needle, haystack, callback) # Result: 'b'@staticmethod
def visit_recursive(input_array, visitor)Recursively visits all elements of an array applying the specified callback to each element key and value.
Arguments:
input_array- The input array whose nodes should be visited.visitor- A callback function that will be called on each array item; the callback will receive the item key and value as input and should return an array that contains the update key and value in the shape [ <key>, <value> ]. Returning a null key will cause the element to be removed from the array.
Returns:
Manipulated array.
my_dict = {'a': 1, 'b': 2}
result = Arr.visit_recursive(my_dict, lambda k, v: (k, v * 2)) # Result: {'a': 2, 'b': 4}@staticmethod
def where(array, callback)Filter the array using the given callback.
Arguments:
array- Array to filter.callbackfunction - Function that returns True if the element should be retained, False otherwise.
Returns:
The filtered array.
def callback(value, key):
return value % 2 == 0
array = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Arr.where(array, callback) # Result: {'b': 2, 'd': 4}@staticmethod
def where_not_none(array)Filter items where the value is not None.
Arguments:
array- Array to filter.
Returns:
The filtered array.
array = {'a': 1, 'b': None, 'c': 3, 'd': None}
Arr.where_not_none(array) # Result: {'a': 1, 'c': 3}@staticmethod
def wrap(value)If the given value is not a list, dict, or UserDict and not None, wrap it in one.
Arguments:
valueAny - Value to wrap.
Returns:
Wrapped value.
Arr.wrap(None) # Result: []
Arr.wrap(1) # Result: [1]
Arr.wrap('hello') # Result: ['hello']
Arr.wrap([1, 2, 3]) # Result: [1, 2, 3]