JavaScript - 以数字方式对2D数组进行排序

时间:2018-04-25 14:14:26

标签: javascript arrays sorting



function getCombinations(_list) {
    var fn = function(active, rest, a) {
        if (!active.length && !rest.length)
            return;
        if (!rest.length) {
            a.push(active);
        } else {
            fn(active.concat(rest[0]), rest.slice(1), a);
            fn(active, rest.slice(1), a);
        }
        return a;
    }
    return fn([], _list, []);
}

var list = [1, 2, 3, 4]

console.log(getCombinations(list));




返回一个2D数组,每个组合都填充...

[ [ 1, 2, 3, 4 ]
, [ 1, 2, 3 ]
, [ 1, 2, 4 ]
, [ 1, 2 ]
, [ 1, 3, 4 ]
, [ 1, 3 ]
, [ 1, 4 ]
, [ 1 ]
, [ 2, 3, 4 ]
, [ 2, 3 ]
, [ 2, 4 ]
, [ 2 ]
, [ 3, 4 ]
, [ 3 ]
, [ 4 ]
]

但我想要以下订单

[ [ 1 ]
, [ 1, 2 ]
, [ 1, 2, 3]
, [ 1, 2, 3, 4 ]
, [ 1, 2, 4]
, [ 1, 3 ]
, [ 1, 3, 4 ]
, [ 1, 4 ]
, [ 2 ]
, ...
, [ 4 ]
]

我尝试使用.sort,但按字母顺序对组合进行排序

getCombinations([ 1, 2, 10 ]).sort()
// [ [ 1 ]
// , [ 1, 10 ]
// , [ 1, 2 ]
// , [ 1, 2, 10 ]
// , [ 10 ]
// , [ 2 ]
// , [ 2, 10 ]
// ]

但这不是我想要的订单。

如何对数组进行排序,以便以数字方式处理数组的内容,结果与上面提到的顺序相同?

5 个答案:

答案 0 :(得分:3)

之后可以使用而不是排序,这是一个直接创建所需组合作为排序结果的函数。

function getCombinations(list) {

    function iter(index, values) {
        var temp = values.concat(list[index]);
        result.push(temp);
        if (++index < list.length) {
            iter(index, temp);
            iter(index, values);
        }
    }

    var result = [];
    iter(0, []);
    return result;
}

var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    result = getCombinations(list);

console.log(result.length);
console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:2)

您可以将比较器函数传递给实现所需排序逻辑的sort()

arr.sort((one, other) => {
    let minL = Math.min(one.length, other.length);
    for (let i = 0; i < minL; i++) {
        if (one[i] != other[i]) return one[i] - other[i];
    }
    return one.length - other.length;
});

答案 2 :(得分:2)

这是用功能编程标记的,所以我想我会展示一种以正确的顺序生成组合的功能方法。

通过功能,我的意思是使用仅运行其输入参数的函数(而不是依赖于外部状态)并返回一个值(而不是依赖于变异)。这与命令式风格形成鲜明对比。

使用Array.prototype.sort既不必要也不实用(它会改变其输入),因此不会在此答案中使用它。

你还提到自从你编写了递归程序以来已经有一段时间了。这应该让轮子再次旋转!

const identity = x =>
  x
  
const concat = (xs, ...ys) =>
  ys.length === 0
    ? xs
    : xs.concat (concat (...ys))
  
const subsets = ([ x, ...xs ], _return = identity) =>
  xs.length === 0
    ? _return ([ [ x ] ])
    : subsets 
        ( xs
        , ss =>
            _return ( concat ( [ [ x ] ]
                             , ss.map (s => concat ([ x ], s))
                             , ss
                             )
                    )
        )
        
for (const set of subsets ([ 1, 2, 3, 4 ]))
  console.log (set)

实现正确的排序

[ 1 ]
[ 1, 2 ]
[ 1, 2, 3 ]
[ 1, 2, 3, 4 ]
[ 1, 2, 4 ]
[ 1, 3 ]
[ 1, 3, 4 ]
[ 1, 4 ]
[ 2 ]
[ 2, 3 ]
[ 2, 3, 4 ]
[ 2, 4 ]
[ 3 ]
[ 3, 4 ]
[ 4 ]

相关:Power Set - 虽然此程序无法生成正确的顺序,但它的简化表单向您展示了如何开始考虑自己解决问题。 concat现在是一个基本的二进制操作,powerSet简化了逻辑分支。

const identity = x =>
  x
  
const concat = (xs, ys) =>
  xs.concat (ys)
  
const None =
  Symbol ()
  
const powerSet = ([ x = None, ...xs ], _return = identity) =>
  x === None
    ? _return ([ [] ]) // base case: no X
    : powerSet         // inductive case: at least one X
        ( xs
        , ss =>
            _return ( concat ( ss.map (s => concat ([ x ], s))
                             , ss
                             )
                    )
        )
          
console.log (powerSet ([ 'x', 'y', 'z' ]))
// [ [ 'x', 'y', 'z' ]
// , [ 'x', 'y' ]
// , [ 'x', 'z' ]
// , [ 'x' ]
// , [ 'y', 'z' ]
// , [ 'y' ]
// , [ 'z' ]
// , []
// ]

尽管不那么复杂,powerSet甚至可以使用空输入,使其成为total function

getCombinations ([])
// => undefined

subsets ([])
// => [ [ undefined ] ]

powerSet ([])
// => [ [] ]

答案 3 :(得分:0)

你可以使用这样的比较函数:

{{1}}

答案 4 :(得分:-1)

你可以模仿这个,通过使用点数或你喜欢的任何其他角色连接数字值来使用自然排序。

import re

s1 = 'H12-H121'
pat = r'^H12'
print(re.sub(pat,"G12",s1))
G12-H121

这是一种使用浮点排序的简写方法。

注意:这是一个技巧,你可以通过更大的列表获得浮点精度错误。

var list = [
  [ 1, 2, 3, 4 ],
  [ 1, 2, 3 ],
  [ 1, 2, 4 ],
  [ 1, 2 ],
  [ 1, 3, 4 ],
  [ 1, 3 ],
  [ 1, 4 ],
  [ 1 ],
  [ 2, 3, 4 ],
  [ 2, 3 ],
  [ 2, 4 ],
  [ 2 ],
  [ 3, 4 ],
  [ 3 ],
  [ 4 ]
];

function versionNumberSort(a, b) {
  return a.join('.').localeCompare(b.join('.'))
}

console.log(list.sort(versionNumberSort).map(l => l.join(', ')).join('\n'));
.as-console-wrapper { top: 0; max-height: 100% !important; }
var list = [
  [ 1, 2, 3, 4 ],
  [ 1, 2, 3 ],
  [ 1, 2, 4 ],
  [ 1, 2 ],
  [ 1, 3, 4 ],
  [ 1, 3 ],
  [ 1, 4 ],
  [ 1 ],
  [ 2, 3, 4 ],
  [ 2, 3 ],
  [ 2, 4 ],
  [ 2 ],
  [ 3, 4 ],
  [ 3 ],
  [ 4 ]
];

function sortNumberArrays(a, b) {
  return parseFloat('0.' + a.join('')) - parseFloat('0.' + b.join(''));
}

console.log(list.sort(sortNumberArrays).map(l => l.join(', ')).join('\n'));