2

ネイティブメソッドを使用して特定の配列をフィルタリングしています。.filter()

var a = [1,2,3,4,5];

var b = a.filter(function(v) {
    return v > 2;
});

これにより、新しい配列 ( [3,4,5]) が作成されます。ここで、フィルター処理された値を別の配列に入れたいと考えています。ここで私の最良の選択肢は何ですか? するべきか

  • 削除された値を同じフィルター メソッドの新しい配列にプッシュしますか?
  • 反転関数を作成し、フィルタリング後に適用しますか?

最初のオプションを使用すると、次のようになる可能性があります。

var b = a.filter(function(v) {
    return v > 2 || !c.push(v);
});

その解決策に関する私の問題は、それが2つの異なるものを混ぜ合わせており、将来コードを読む人にとって非常に混乱する可能性があることです. 別の方法として、次のようなものを呼び出すことができます

c = invert(a,b);

function invert(source, compare) {
    return source.filter(filterPositives);

    function filterPositives(v) {
        return compare.indexOf(v) === -1;
    };
}

それは効果的ですか?それとも私はもっとうまくやれますか?

この問題を解決する他の(よりエレガントな)アイデアはありますか?

4

4 に答える 4

3

ソース配列を 2 回通過することは、洗練された解決策ではないと思います。しかし、繰り返しますが、自分自身に副作用を追加することfilterも素晴らしいことではありません.

filterSplitこの疑似コードのような関数を書くことで問題を解決します。

function filterSplit(
      Array source, Array positives, Array negatives, Function filterCb) 
{
  source.forEach(function(el) {
    if (filterCb(el)) {
      positives.push(el); 
    }
    else {
      negatives.push(el);
    }
  }
}

...または、戻り値に配列を使用したい場合...

function anotherFilterSplit(Array source, Function filterCb) {
  var positives = [], negatives = [];
  // ... the same check and push as above ...
  return [positives, negatives];
}
于 2012-09-05T11:05:20.077 に答える
0

Andrew D.はすでに良い答えを書いているので、これを書くべきかどうかはわかりませんが、次のようになります。

http://jsfiddle.net/BsJFv/2/

Array.prototype.divide = function(fun, neg) {
    if (this == null) throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun != "function") throw new TypeError();

    if (!(neg instanceof Array)) {
        throw new TypeError();
    }

    var res = [];
    neg.splice(0, neg.length);
    var thisp = arguments[2];
    for (var i = 0; i < len; i++) {
        if (i in t) {
            var val = t[i];
            if (fun.call(thisp, val, i, t)) {
                res.push(val);
            }
            else {
                neg.push(val);
            }
        }
    }

    return res;
};

このようにして、優れた除算機能が得られました。

最初のパラメーターは分割する関数であり、2番目のパラメーターは負の値の配列です。

唯一の制限は、呼び出しの前に2番目のパラメーターを配列としてインスタンス化する必要があることです。

var negatives = [];
var positives = x.divide(function(elem) {
    /* whatever you want to check */
}, negatives);
于 2012-09-05T11:47:33.070 に答える
0

@raina77owのソリューションは良さそうです。一体、 Cocoでの実装は次のとおりです。

function filterSplit (source, predicate, positives = [], negatives = [])
  source.forEach -> (if predicate it then positives else negatives).push el
  return [positives, negatives]

コンパイルされたJavaScript

function filterSplit(source, predicate, positives, negatives){
  positives == null && (positives = []);
  negatives == null && (negatives = []);
  source.forEach(function(it){
    return (predicate(it) ? positives : negatives).push(el);
  });
  return [positives, negatives];
}

--したがって、positivesとを渡すか、パスしnegativesないままにしておくことができます。その場合、新しい空の配列が取得されます。

于 2012-09-05T11:13:35.667 に答える
0
var a=[1,2,3,4,5],b=[],c=[];

for(var i=0,l=a.length,ai=a[i];i<l;ai=a[++i])
    if(ai>2)b.push(ai);
    else c.push(ai);

console.log(b,c);
// [3, 4, 5]   [1, 2]
于 2012-09-05T11:12:05.727 に答える