All Projects → adrienjt → Redux Data Structures

adrienjt / Redux Data Structures

Licence: mit
Reducer factory functions for common data structures: counters, maps, lists (queues, stacks), sets, etc.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Redux Data Structures

Buckets Js
A complete, fully tested and documented data structure library written in pure JavaScript.
Stars: ✭ 1,128 (+618.47%)
Mutual labels:  data-structures, stack, dictionary, set, queue, map
Javascript Datastructures Algorithms
📚 collection of JavaScript and TypeScript data structures and algorithms for education purposes. Source code bundle of JavaScript algorithms and data structures book
Stars: ✭ 3,221 (+1951.59%)
Mutual labels:  data-structures, stack, dictionary, set, queue
Containers
This library provides various containers. Each container has utility functions to manipulate the data it holds. This is an abstraction as to not have to manually manage and reallocate memory.
Stars: ✭ 125 (-20.38%)
Mutual labels:  data-structures, stack, set, queue, map
Mlib
Library of generic and type safe containers in pure C language (C99 or C11) for a wide collection of container (comparable to the C++ STL).
Stars: ✭ 321 (+104.46%)
Mutual labels:  stack, dictionary, set, queue
Libgenerics
libgenerics is a minimalistic and generic library for C basic data structures.
Stars: ✭ 42 (-73.25%)
Mutual labels:  data-structures, stack, queue, map
Algorithm
Algorithm is a library of tools that is used to create intelligent applications.
Stars: ✭ 787 (+401.27%)
Mutual labels:  data-structures, stack, dictionary, set
Collectable
High-performance immutable data structures for modern JavaScript and TypeScript applications. Functional interfaces, deep/composite operations API, mixed mutability API, TypeScript definitions, ES2015 module exports.
Stars: ✭ 233 (+48.41%)
Mutual labels:  data-structures, dictionary, set, map
Geeksforgeeks Dsa 2
This repository contains all the assignments and practice questions solved during the Data Structures and Algorithms course in C++ taught by the Geeks For Geeks team.
Stars: ✭ 53 (-66.24%)
Mutual labels:  data-structures, stack, queue
Cdcontainers
Library of data containers and data structures for C programming language.
Stars: ✭ 57 (-63.69%)
Mutual labels:  stack, queue, map
Imtools
Fast and memory-efficient immutable collections and helper data structures
Stars: ✭ 85 (-45.86%)
Mutual labels:  data-structures, dictionary, map
Gostl
Data structure and algorithm library for go, designed to provide functions similar to C++ STL
Stars: ✭ 254 (+61.78%)
Mutual labels:  stack, set, queue
Algodeck
An Open-Source Collection of 200+ Algorithmic Flash Cards to Help you Preparing your Algorithm & Data Structure Interview 💯
Stars: ✭ 4,441 (+2728.66%)
Mutual labels:  data-structures, stack, queue
Gods
GoDS (Go Data Structures). Containers (Sets, Lists, Stacks, Maps, Trees), Sets (HashSet, TreeSet, LinkedHashSet), Lists (ArrayList, SinglyLinkedList, DoublyLinkedList), Stacks (LinkedListStack, ArrayStack), Maps (HashMap, TreeMap, HashBidiMap, TreeBidiMap, LinkedHashMap), Trees (RedBlackTree, AVLTree, BTree, BinaryHeap), Comparators, Iterators, …
Stars: ✭ 10,883 (+6831.85%)
Mutual labels:  stack, set, map
Redisson
Redisson - Redis Java client with features of In-Memory Data Grid. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Publish / Subscribe, Bloom filter, Spring Cache, Tomcat, Scheduler, JCache API, Hibernate, MyBatis, RPC, local cache ...
Stars: ✭ 17,972 (+11347.13%)
Mutual labels:  set, queue, map
Collections.pooled
Fast, low-allocation ports of List, Dictionary, HashSet, Stack, and Queue using ArrayPool and Span.
Stars: ✭ 115 (-26.75%)
Mutual labels:  stack, dictionary, queue
Learningmasteringalgorithms C
Mastering Algorithms with C 《算法精解:C语言描述》源码及Xcode工程、Linux工程
Stars: ✭ 615 (+291.72%)
Mutual labels:  stack, set, queue
Data Structures
This repository contains some data structures implementation in C programming language. I wrote the tutorial posts about these data structures on my personal blog site in Bengali language. If you know Bengali then visit my site
Stars: ✭ 82 (-47.77%)
Mutual labels:  data-structures, stack, queue
Data-structures
Data Structures in Java
Stars: ✭ 13 (-91.72%)
Mutual labels:  stack, queue, data-structures
js-collections-map-set
Repository to have example code to demonstrate JavaScript Map and Set data structures.
Stars: ✭ 21 (-86.62%)
Mutual labels:  map, set, data-structures
Collection
A PHP library for representing and manipulating collections.
Stars: ✭ 488 (+210.83%)
Mutual labels:  set, queue, map

Redux Data Structures

Introduction

Redux Data Structures is a library of reducer makers.

Reducer makers help create common reducers like counters, maps, lists (queues, stacks), sets, etc. Most application states can be built by combining a handful of these standardized building blocks.

Redux Data Structures was developed for Redux, but does not depend on it. It can actually be used with any reactive state container, even a custom one; Redux Data Structures doesn't have any dependency.

Getting Started

npm install --save redux-data-structures

Here's an example from the Redux README, rewritten with Redux Data Structures:

import { createStore } from 'redux';
import { counter } from 'redux-data-structures';

const myCounter = counter({
  incrementActionTypes: ['INCREMENT'],
  decrementActionTypes: ['DECREMENT'],
});

const store = createStore(myCounter);

store.subscribe(() => { console.log(store.getState()); });

store.dispatch({ type: 'INCREMENT' });
// 1
store.dispatch({ type: 'INCREMENT' });
// 2
store.dispatch({ type: 'DECREMENT' });
// 1

Configuring Data Structures

Here's a more advanced example--with the same reducer maker--of a counter from 10 to 0, decreasing as a function of the action payload, then reset, representing life points for example:

import { createStore } from 'redux';
import { counter } from 'redux-data-structures';

const lifePoints = counter({
  initialState: 10,
  decrementActionTypes: ['PUNCH', 'KICK'],
  decrement: action => action.value,
  min: () => 0, // action => number
  resetActionTypes: ['INSERT_COIN'],
});

const store = createStore(lifePoints);

store.subscribe(() => { console.log(store.getState()); });

store.dispatch({ type: 'PUNCH', value: 5 });
// 5
store.dispatch({ type: 'KICK', value: 7 });
// 0
store.dispatch({ type: 'INSERT_COIN' });
// 10

Combining Data Structures

Let's build a classic todo app with Redux Data Structures:

import { createStore, combineReducers } from 'redux';
import { map, set, value } from 'redux-data-structures';

const todos = map({
  addActionTypes: ['ADD_TODO'],
  removeActionTypes: ['REMOVE_TODO'],
});

const completedTodos = set({
  toggleActionTypes: ['TOGGLE_TODO'],
  removeActionTypes: ['REMOVE_TODO'],
  keyGetter: action => action.payload.id,
});

const visibilityFilter = value({
  initialState: 'SHOW_ALL',
  setActionTypes: ['SET_VISIBILITY_FILTER'],
  valueGetter: action => action.payload.filter,
});

const rootReducer = combineReducers({
  todos,
  completedTodos,
  visibilityFilter,
});

const store = createStore(rootReducer);

That's all for the store! We've relied heavily on the reducer makers' default options, which presume that:

  1. actions adhere to the Flux Standard Action (actions are plain Javascript object with a type and payload properties),
  2. and Todos are identified by an id property, used as a key in the todos map (and the completetedTodos set).

Now let's subscribe to the store and dispatch a few actions:

store.subscribe(() => { console.log(JSON.stringify(store.getState(), null, 2)); });

store.dispatch({
  type: 'ADD_TODO',
  payload: {
    id: 0,
    text: 'Go fishing',
  },
});
// {
//   "todos": {
//     "byId": {
//       "0": {
//         "id": 0,
//         "text": "Go fishing"
//       }
//     },
//     "allIds": [
//       0
//     ]
//   },
//   "completedTodos": {},
//   "visibilityFilter": "SHOW_ALL"
// }

Notice that todos is normalized, for the reasons explained in the Redux documentation.

store.dispatch({
  type: 'TOGGLE_TODO',
  payload: { id: 0 },
});
// {
//   "todos": {
//     "byId": {
//       "0": {
//         "id": 0,
//         "text": "Go fishing"
//       }
//     },
//     "allIds": [
//       0
//     ]
//   },
//   "completedTodos": {
//     "0": true
//   },
//   "visibilityFilter": "SHOW_ALL"
// }

Compared to the original Redux Todo example, we've separated the Todo items (id, text) from their completion state. If needed, they could be combined with a selector.

store.dispatch({
  type: 'SET_VISIBILITY_FILTER',
  payload: { filter: 'SHOW_COMPLETED' },
});
// {
//   "todos": {
//     "byId": {
//       "0": {
//         "id": 0,
//         "text": "Go fishing"
//       }
//     },
//     "allIds": [
//       0
//     ]
//   },
//   "completedTodos": {
//     "0": true
//   },
//   "visibilityFilter": "SHOW_COMPLETED"
// }
store.dispatch({
  type: 'REMOVE_TODO',
  payload: { id: 0 },
});
// {
//   "todos": {
//     "byId": {},
//     "allIds": []
//   },
//   "completedTodos": {},
//   "visibilityFilter": "SHOW_COMPLETED"
// }

The REMOVE_TODO action is reduced both by the todos map and the completedTodos set.

Data Structures

So far, the following data structures have been implemented (corresponding action types are indicated in parentheses):

  • Boolean (set to true, set to false, toggle)
  • Counter (increment, decrement)
  • List (queue or stack: enqueue, dequeue, push, pop)
  • Map (add, remove, change)
  • Set (add, remove, toggle)
  • Value (set)

All data structures can be reset to their initial state, and, if applicable (for lists, maps, and sets), emptied.

API

Each reducer maker is a higher-order function of a single options object and returns a reducer:

{ ...options } => (state, action) => state

For each reducer maker, we describe below how the options object is destructured, its default property values, and how some specific properties are used.

Defaults can--and in a lot of cases should--be overridden.

Each category of actions, e.g., decrementActionTypes, is an array of action types (i.e., strings), so that several action types can have the same result (cf. Configuring Data Structures, above, where both PUNCH and KICK decrement lifePoints).

Boolean

{
  initialState = false,
  trueActionTypes = [],
  additionalConditionToTrue = () => true,
  falseActionTypes = [],
  additionalConditionToFalse = () => true,
  toggleActionTypes = [],
  resetActionTypes = [],
}

additionalConditionToTrue and additionalConditionToFalse are functions of action and are used as such:

// ...
if (trueActionTypes.includes(action.type) && additionalConditionToTrue(action)) {
  return true;
} else if (falseActionTypes.includes(action.type) && additionalConditionToFalse(action)) {
  return false;
}
// ...

The default () => true is equivalent to no additional condition.

Counter

{
  initialState = 0,
  incrementActionTypes = [],
  increment = () => 1,
  max,
  decrementActionTypes = [],
  decrement = () => 1,
  min,
  resetActionTypes = [],
}

increment, decrement, max, and min are functions of action. If max is undefined, it is not enforced. Same for min.

List

{
  initialState = [],
  enqueueActionTypes = [],
  dequeueActionTypes = [],
  pushActionTypes = [],
  popActionTypes = [],
  itemGetter = action => action.payload,
  resetActionTypes = [],
  emptyActionTypes = [],
}

A list can be used as a queue or stack. enqueueActionTypes and pushActionTypes add items to the list, using the itemGetter. The default itemGetter adds the Flux Standard Action payload to the list.

Map

{
  initialState = {
    byId: {},
    allIds: [],
  },
  addActionTypes = [],
  changeActionTypes = [],
  removeActionTypes = [],
  keyGetter = action => action.payload.id,
  itemGetter = action => ({...action.payload}),
  itemModifier = (item, action) => ({...item, ...action.payload}),
  resetActionTypes = [],
  emptyActionTypes = [],
}

map uses the normalized state shape recommended by Redux, as can be seen from the default initialState. Warning: if you overwrite initialState, use the same format!

The default keyGetter assumes that the action payload has an id property. The default itemModifier overwrites the item's properties (but does not delete the ones that have disappeared in the new action payload).

Set

{
  initialState = {},
  addActionTypes = [],
  removeActionTypes = [],
  toggleActionTypes = [],
  keyGetter = action => action.payload,
  resetActionTypes = [],
  emptyActionTypes = [],
}

In Redux Data Structures, a set's state is a plain Javascript object with boolean properties, i.e. if and only if key is in the set, key is a property of state whose value is true. Example:

{ key: true }

When a key is removed from the set, the corresponding property is deleted from the state object:

{}

Value

{
  initialState = null,
  setActionTypes = [],
  valueGetter = action => action.payload,
  resetActionTypes = [],
}

value is the simplest data structure (to the extent that calling it a data structure is arguable).

Performance

Redux Data Structures doesn't focus on performance, but on developer productivity. In most cases, performance won't be an issue. If it is, please write an issue or submit a pull request.

Contributing

The code is written in modern Javascript, transpiled with Babel, using Jest for tests. Pull requests are welcome.

License

MIT

Author

Adrien Trouillaud, Codology.net

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].