Javascript 某些项目何时以及为什么不';甚至不能在排序算法中进行比较?

Javascript 某些项目何时以及为什么不';甚至不能在排序算法中进行比较?,javascript,arrays,node.js,sorting,Javascript,Arrays,Node.js,Sorting,我有一个例子,需要按多个条件对字符串数组进行排序。假设我们正在复制一个目录路径列表。鉴于下面的要求,我需要排序来生成始终相同的结果。输入的初始顺序应该无关紧要 每个项目都是一个路径字符串,可能包含一个全局/通配符星号*。 e、 g.*/foo或foo/*或foo/*/bar。。你明白了 每个项目可能也包含前缀将该值取反。 e、 g.!bar/norf表示删除此路径 要求: 如果两条比较的路径相等,且其中一条路径被求反(!);被否定的应该排在最后。 e、 g.bar/norf在之前!条码 级别

我有一个例子,需要按多个条件对字符串数组进行排序。假设我们正在复制一个目录路径列表。鉴于下面的要求,我需要排序来生成始终相同的结果。输入的初始顺序应该无关紧要

  • 每个项目都是一个路径字符串,可能包含一个全局/通配符星号
    *

    e、 g.
    */foo
    foo/*
    foo/*/bar
    。。你明白了
  • 每个项目可能也包含前缀
    将该值取反。
    e、 g.
    !bar/norf
    表示删除此路径
要求:
  • 如果两条比较的路径相等,且其中一条路径被求反(
    );被否定的应该排在最后。 e、 g.
    bar/norf
    之前!条码
  • 级别数较少的路径应排在第一位。
    e、 g.
    foo/bar
    位于
    foo/baz/*
  • 松散路径/全局路径应排在第一位,详细路径/精确路径应排在最后。
    e、 g.
    foo/*
    foo/bar/*
    之前,在
    foo/bar/baz
    之前
  • 尝试: 现在,如果我使用诸如快速排序或合并排序之类的算法,大多数时候我都会得到预期的结果,但是当我更改初始顺序或项目数量时,它会失败。特别是对于上面的第一个要求。贝克。有时(取决于初始订单或项目数量),一些项目不能直接相互比较

    var unsorted_CASE1=[
    ‘foo/bar/baz’,
    “!bar/norf”,
    ‘bar/x’,
    “巴/北”,
    “!foo/*/baz”,
    “!bar/*”,
    ‘foo/qux/*’
    ];
    日志(mergeSort(未排序的案例1,compareFn));
    //预期正确输出
    [ 
    “!bar/*”,//0
    'bar/norf',//1
    “!bar/norf”,//2
    'bar/x',//3
    “!foo/*/baz”,//4
    'foo/qux/*',//5
    'foo/bar/baz'//6
    ]
    未分类的变量_案例2=[
    ‘foo/bar/baz’,
    “!bar/norf”,
    ‘bar/x’,
    “巴/北”,
    “!foo/*/baz”,
    “!bar/*”,
    “!foo/qux/boo”,//在此处添加了一个新项,没有其他更改
    ‘foo/qux/*’
    ];
    日志(mergeSort(未排序的案例2,compareFn));
    //输出错误
    [ 
    “!bar/*”,//0
    “!bar/norf',//1(应该在bar/norf(3)之后)
    'bar/x',//2
    'bar/norf',//3
    “!foo/*/baz”,//4
    'foo/qux/*',//5
    ‘foo/bar/baz’,//6
    “!foo/qux/boo”//7
    ]
    
    这里是
    !bar/norf'
    'bar/norf'
    从未直接相互比较。结果,否定词排在第一位,而否定词则排在第二位

    编辑1:我不是要求实现排序算法。我当然是在使用外部libs。我试图理解某些项目何时以及为什么不能进行比较并产生这样的结果。这里使用的排序算法是否需要所有可能的排列才能得到预期的结果。如果不是,哪种著名的算法最适合这里?还是不是排序算法?就这些

    编辑2: 下面是比较函数:

    功能比较(oA,oB){
    变量aNeg=oA.slice(0,1)=='!',
    bNeg=oB.slice(0,1)=='!',
    a=平均?oA.切片(1):oA,
    b=bNeg?oB.切片(1):oB;
    //“foo/bar”vs“!foo/bar”»equal»否定胜利(最后一名)
    如果(a==b){
    返回aNeg?1:-1;
    }
    //如果不相等»例如“!*/foo/*”与“*/foo/bar”
    //“*/foo/bar”排在最后
    变量A=A.split('/'),
    B=B.split('/'),
    numLevelsA=A.长度,
    numLevelsB=B.长度;
    //级别数较少的glob首先出现
    //例如,“bar/*”位于“bar/baz/*”之前
    if(numLevelsAnumLevelsB | | b==='*'){return 1;}//b first
    //级别数相等:
    var lA,lB,i=-1;
    而(++i=0&&lB.indexOf('*')<0){return-1;}
    如果(lA.indexOf('*')<0&&lB.indexOf('*')>=0){return 1;}
    }
    //否则,如果级别相等,
    //继续到下一个层次
    }
    //没有秩序
    返回0;
    };
    

    注意:这是问题的一个非常简化的版本。我没有实现minimatch或类似的库。(事实上,项不是偶数路径字符串)。因此,请不要建议已经这样做的LIB。我正在尝试建立/理解逻辑。

    我从头重写了比较函数,我认为这个函数有效:

    function compare(a, b) {
        // trivial case, both are exactly the same!
        if (a === b) {
            return 0;
        }
        var levelsA = a.split("/");
        var levelsB = b.split("/");
    
        // Check depth (number of levels)
        if (levelsA.length === levelsB.length) {
            // count wildcards (assuming more wildcards comes first)
            var wild = /(?:^|\/)\*(?:$|\/)/g;
            var mA = a.match(wild);
            var mB = b.match(wild);
            var wildA = mA ? mA.length : 0;
            var wildB = mB ? mB.length : 0;
            if (wildA === wildB) {
                // check for negation
                var negA = a.indexOf("!") === 0;
                var negB = b.indexOf("!") === 0;
                if (negA === negB) {
                    // both are negated or neither are, just return alphabetical
                    return a < b ? -1 : 1;
                }
                // compare without the negatation
                var nonNegA = negA ? a.slice(1) : a;
                var nonNegB = negB ? b.slice(1) : b;
                if (nonNegA === nonNegB) {
                    return negA ? 1 : -1;
                }
                return nonNegA < nonNegB ? -1 : 1;
    
            }
            return wildA > wildB ? -1 : 1;
        }
    
        return levelsA.length < levelsB.length ? -1 : 1;
    }
    
    给出:

    [
        "!bar/*",
        "bar/norf",
        "!bar/norf",
        "bar/x",
        "!foo/*/baz",
        "foo/qux/*",
        "foo/bar/baz",
        "!foo/qux/boo"
    ]
    

    问题在哪里?你要的是算法吗?询问事物是如何工作的?你应该使用哪种算法?如果你在问标题中提出的问题,为什么不包括比较?看起来不太清楚您在寻找什么样的答案。@OnurYıldırım JavaScript规范并不要求排序算法的稳定性。所以这纯粹是一个实现细节。问题真的是哪个“排序算法”?只要排序比较有一个总的顺序,它实际上并不重要——如果没有,它就不是一个“排序”问题。你到底需要什么?把它说清楚。对我来说,你的比较函数似乎是个问题,但你似乎完全忽略了这种可能性,我认为这是所有这些混乱的根源。根据提供的标准,我希望比较函数首先比较路径,然后按照字母顺序从第一条路径到最后一条路径,最后是
    [
        "!bar/*",
        "bar/norf",
        "!bar/norf",
        "bar/x",
        "!foo/*/baz",
        "foo/qux/*",
        "foo/bar/baz",
        "!foo/qux/boo"
    ]