Sort two arrays the same way

前端 未结 12 2266
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-27 15:48

For example, if I have these arrays:

var name = [\"Bob\",\"Tom\",\"Larry\"];
var age =  [\"10\", \"20\", \"30\"];

And I use name.sort

12条回答
  •  忘掉有多难
    2020-11-27 16:32

    I was looking for something more generic and functional than the current answers.

    Here's what I came up with: an es6 implementation (with no mutations!) that lets you sort as many arrays as you want given a "source" array

    /**
     * Given multiple arrays of the same length, sort one (the "source" array), and
     * sort all other arrays to reorder the same way the source array does.
     * 
     * Usage:
     * 
     * sortMultipleArrays( objectWithArrays, sortFunctionToApplyToSource )
     * 
     * sortMultipleArrays(
     *   {
     *    source: [...],
     *    other1: [...],
     *    other2: [...]
     *   },
     *   (a, b) => { return a - b })
     * )
     * 
     * Returns:
     *   {
     *      source: [..sorted source array]
     *      other1: [...other1 sorted in same order as source],
     *      other2: [...other2 sorted in same order as source]
     *   }
     */
    export function sortMultipleArrays( namedArrays, sortFn ) {
        const { source } = namedArrays;
        if( !source ) {
            throw new Error('You must pass in an object containing a key named "source" pointing to an array');
        }
    
        const arrayNames = Object.keys( namedArrays );
    
        // First build an array combining all arrays into one, eg
        // [{ source: 'source1', other: 'other1' }, { source: 'source2', other: 'other2' } ...]
        return source.map(( value, index ) =>
            arrayNames.reduce((memo, name) => ({
                ...memo,
                [ name ]: namedArrays[ name ][ index ]
            }), {})
        )
        // Then have user defined sort function sort the single array, but only
        // pass in the source value
        .sort(( a, b ) => sortFn( a.source, b.source ))
        // Then turn the source array back into an object with the values being the
        // sorted arrays, eg
        // { source: [ 'source1', 'source2' ], other: [ 'other1', 'other2' ] ... }
        .reduce(( memo, group ) =>
            arrayNames.reduce((ongoingMemo, arrayName) => ({
                ...ongoingMemo,
                [ arrayName ]: [
                    ...( ongoingMemo[ arrayName ] || [] ),
                    group[ arrayName ]
                ]
            }), memo), {});
    }
    

提交回复
热议问题