-1

たとえば、次のようなものがあるとします。

var Constants = {
  scope:{
    namespaceA: { A_X: "TEST_AX" , A_Y: "TEST_AY" },
    namespaceN: { N_X: "TEST_NX" , N_Y: "TEST_NY" }
  }
  _mapping: [],
  getMapping: function(){...}
}

var flattenList = flatten(Constants.scope); //returns ["TEST_AX","TEST_AY","TEST_NX","TEST_NY"]
var anotherWayFlattened = flatten(Constants.scope.namespaceA,Constants.scope.namespaceB); //returns same result as above

編集: 1 つの方法は、for-each ループを介してスコープを反復処理することですが、もっとエレガントなものを探していましたか?

二重編集:わかりました、私はちょうど次のように何かをホイップしました:

var flattenedList = (function(list){
    var flatList = []
    $.each(list,function(i,items){
        for(var p in items) flatList.push(items[p]);
    })
    return flatList;
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);

しかし、特定のプロパティを渡すのを避けて、定数を渡して名前空間のリストを検索できるかどうか疑問に思っていました

4

3 に答える 3

1

これは、より深いネストを可能にするアプローチです。それが目標の一部ではなかったことは知っていますが、もっと興味深い問題だと思いました。:-)

var flatten = (function() {
    var toString = Object.prototype.toString, slice = Array.prototype.slice;
    var flatten = function(input, output) {
        var value;
        output = (toString.call(output) == "[object Array]") ? output : [];
        for (name in input) {if (input.hasOwnProperty(name)) {
            value = input[name];
            if (toString.call(value) == "[object Object]") {
                flatten(value, output);
            } else {
                output.push(value);
            }
        }};
        return output;
    };
    var merge = function(first, second) {
        return first.concat(second);
    }

    return function() {
        return slice.call(arguments).map(flatten).reduce(merge);
    };
}());

これにより、次のいずれかのアプローチが可能になります。

flatten(Constants.scope);
flatten(Constants.scope.namespaceA, Constants.scope.namespaceN);

必要な数の個別の引数、または1つの引数を渡すことができます。それらはすべて任意の深さまで検索されます。

Array.prototype一部の環境では、関数mapとをシムする必要がある場合がありますreduce

于 2013-02-13T20:47:41.137 に答える
1

任意の (循環的でない!) 深さまで再帰したい場合は、次のようにすることができます。

function flattenList(list, accumulator){
    accumulator = accumulator || [];
    for(var p in list){
        if(list.hasOwnProperty(p)) {
            if(typeof list[p] === "string") {
                accumulator.push(list[p]);
            } else if(typeof list[p] === "object") { // this is not a reliable test!
                flattenList(list[p], accumulator);
            }
        }
    }
    return accumulator;
}

このコードは、オブジェクトの最後に文字列しかないなど、多くの仮定を立てています。または、深さが事前にわかっている場合は、 concat を使用して現在のソリューションを最適化できます。

var flattenedList = (function(list){
    return Array.prototype.concat.apply([], list);
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);
于 2013-02-13T19:56:22.210 に答える
1

[Constants.scope.namespaceA,Constants.scope.namespaceB]

サブオブジェクトを配列で明示的に渡す理由が不思議です。Constants.scopeオブジェクト全体を渡さないのはなぜですか?

var flattenedList = (function(obj){
    var flatList = []
    for (var prop in obj) {
        var items = obj[prop];
        for (var p in items)
            flatList.push(items[p]);
    }
    return flatList;
})(Constants.scope);

あなたのコメントから、これが欲しかったようです:

var flattenedList = (function(obj, test){
    var flatList = []
    for (var prop in obj) {
        if (!test(prop))
            continue;
        var items = obj[prop];
        for (var p in items)
            flatList.push(items[p]);
    }
    return flatList;
})(Constants, function(name) {
    return name.substr(0, 9) == "namespace";
    // or maybe
    return /^namespace[A-Z]$/.test(name);
});
于 2013-02-13T19:46:30.090 に答える