data_array-diff.js

import isObject from './is-object';

/**
 * @module arrayDiff
 * @description Returns an object containing the added and removed items between two arrays.
 *
 * @since 4.0.7
 *
 * @param {Array}           fromArr The from array.
 * @param {Array}           toArr   The to array.
 * @param {string|Function} key     The key to use for the comparison. If a function is provided, it will be used to get the key.
 *
 * @return {object} An object containing the added and removed items.
 *
 * @example
 * const fromArr = [ 1, 2, 3 ];
 * const toArr = [ 1, 2, 3, 4, 5 ];
 * const diff = arrayDiff( fromArr, toArr );
 * console.log( diff );
 * // { added: [ 4, 5 ], removed: [] }
 *
 * @example
 * const fromArr = [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' } ];
 * const toArr = [ { id: 1, name: 'John' }, { id: 2, name: 'Jane' }, { id: 3, name: 'Joe' } ];
 * const diff = arrayDiff( fromArr, toArr, 'id' );
 * console.log( diff );
 * // { added: [ { id: 3, name: 'Joe' } ], removed: [] }
 *
 */
const arrayDiff = ( fromArr = [], toArr = [], key = null ) => {
	const getValue = ( item ) => {
		if ( key !== null ) {
			if ( typeof key === 'function' ) {
				return key( item );
			} else if ( isObject( item ) ) {
				return item[ key ];
			}
		}
		return item;
	};

	const fromArrValues = new Set( fromArr.map( getValue ) );
	const toArrValues = new Set( toArr.map( getValue ) );
	const added = toArr.filter( ( item ) => ! fromArrValues.has( getValue( item ) ) );
	const removed = fromArr.filter( ( item ) => ! toArrValues.has( getValue( item ) ) );

	return {
		added,
		removed,
	};
};

export default arrayDiff;