5

次のようなオブジェクトがあります。

{
    a : 'foo',
    b : 'bar',
    c : 'foo',
    d : 'baz',
    e : 'bar'
}

次のような重複を減らしたい:

{
    ac : 'foo',
    be : 'bar',
    d : 'baz'
}

それを行う良い方法は何ですか?

いくつかの注意事項:

  • 少数のペアしか存在しません。(現在は 7 つあります。たとえば、20 まで増えると想像できます。)
  • 例のように、最初のプロパティ名は 1 文字のみです。
  • 値は数百文字になる可能性があります。
  • 速度とコード長の両方が非常に重要ですが、行数が少ないため、コードの明瞭さがおそらく最も重要です。
4

6 に答える 6

1
var Reduce = function(obj)
{
  var temp = {};
  var val = "";

  for (var prop in obj)
  {
    val = obj[prop];
    if (temp[val])
      temp[val] = temp[val] + prop.toString();
    else
      temp[val] = prop.toString();
  }

  var temp2 = {};

  for (var prop in temp)
  {
    val = temp[prop];
    temp2[val] = prop.toString();
  }

  return temp2;
};

使用:

var obj = {
  a :"foo",
  b : "bar",
  c : "foo",
  d : "bar", 
  e : "bar"
};

var ob2 = Reduce(obj);
于 2011-01-06T23:25:49.450 に答える
1

これは私が得ることができる最短のものです:

var obj, newObj = {}; // obj is your original
for (var i in obj) {
    if (!obj.hasOwnProperty(i)) continue;
    for (var j in newObj) {
        if (newObj.hasOwnProperty(j) && newObj[j] === obj[i]) break;
        j = "";
    }
    newObj[i + j] = obj[i];
    j && delete newObj[j];
}

説明:

  • 元のオブジェクト の各項目をループしobj、新しいオブジェクト を生成しますnewObj
  • オリジナルの各アイテムについて、半分生産さnewObjれたものから同じ値を検索します。- 結果はj、見つかった場合はプロパティの名前、見つからなかった場合は空の文字列です。
  • いずれの場合も、新しいオブジェクトには、元のオブジェクトの現在のプロパティと同じ名前のプロパティに加えて、この の値が必要jです。
  • また、見つかったプロパティが存在するnewObj場合は削除して、重複が構築されるのを防ぎます。

確かにj = ""、ループ内での設定は非効率的です。これは、一致が見つかった場合""にのみ、最初に設定された 2 番目の変数に簡単に置き換えることができます。j私はシンプルに行くことにしました。

于 2011-01-06T23:51:41.803 に答える
1

より高い種類のライブラリがなければ、各ペアをループし ( を使用hasOwnProperty)、ヒストグラム キーがペア値であり、ヒストグラム値が連結されたキーであるヒストグラムにキーを追加/追加します。次に、ヒストグラムのキー/値を逆にします。

編集:初期値が文字列でない場合 (および可逆的にマップされない場合)、既存の「ID ハッシュ」ライブラリでも上記のアプローチが機能する可能性があります。

または、マッピングしてソートし、バケット ソート[[k,v],...](既にソートされていると想像してください) に似たアプローチを使用して、出力パスの「等しいキー」の値をマージすることもできます。

次のようになります (コードにはバグがあるかもしれませんが、アプローチは適切です。値を比較する方法がある限り、任意のオブジェクトを値として使用することもできます)。

var _f = []
for (var k in map) {
  if (map.hasOwnProperty(k)) {
    _f.push({k: k, v: map[k]})
  }
}
// you could also sort on name (a.k), if it's important
// this makes it more versatile and deterministic in output
// ordering than the histogram method above
var f = _f.sort(function (a, b) { return a.v < b.v ? 1 : a.v > b.v ? -1 : 0 })

var res = {}
var prev
var name = ""
// after the sort all {k:,v:} objects with the same values will be grouped
// together so we only need to detect the change to the next value
// and everything prior to that gets the merged key
for (var i = 0; i < f.length; i++) {
  var p = f[i]
  if (prev != p.v && name) {
    res[name] = prev
    name = ""
  } else {
    name = name + p.k
  }
  prev = p.v
}
if (name) { // don't forget last set of values
  res[name] = prev
}

// have res
于 2011-01-06T23:10:21.993 に答える
0

反転した方法でタグをカウントするために辞書を使用する reduce から始めます。組み込みの辞書サポートを使用し、for ループなどを使用しないため、非常にパフォーマンスの高い方法です。

var flipped = Object.keys(input).reduce(function(a,b){
  var tag = input[b];
  a[tag] = (a[tag] || '') + b;
  return a;
}, {});

反転された形式のオブジェクトを返します。

// {foo: "ac", bar: "be", baz: "d"}

次に、フォーマットを反転します。

Object.keys(flipped).reduce(function(a,b){
  a[flipped[b]]=b;
  return a;
}, {});

出力:

// {ac: "foo", be: "bar", d: "baz"}
于 2015-07-18T12:57:31.363 に答える
0

オブジェクトの各プロパティを調べて、のオブジェクトを作成します。ここで、キーは最初の値であり、値はキーのリストです (最初から)。次に、その 2 番目のオブジェクトに戻り、最終結果を作成します。

このようなもの:

function noDupes(obj) {
  var o2 = {};
  for (var k in obj) {
    if (obj.hasOwnProperty(k)) {
      var list = o2[obj[k]] || [];
      list.push(k);
      o2[obj[k]] = list;
    }
  }
  var rv = {};
  for (k in o2) {
    if (o2.hasOwnProperty(k))
      rv[o2[k].join('')] = k;
  }
  return rv;
}

ここで、元のオブジェクトの値が文字列でない場合、事態はさらに複雑になります。文字列のみが Javascript オブジェクトのプロパティ キーになることができます。その場合、より一般的なハッシュの実装を探すことができます。オブジェクトが非常に小さい (プロパティが 10 個程度に満たない) 傾向にある場合は、n 2バージョンを書き出すことができます。このバージョンでは、単にプロパティを反復処理してから、各プロパティに対して再度反復処理を行います。ただし、オブジェクトが大きく、この操作を頻繁に実行する必要がある場合、これはおそらく悪い考えです。

于 2011-01-06T23:09:11.527 に答える
0

私が完全に外れた場合は申し訳ありませんが、これらを組み合わせる方法では、キーと値が間違った方法で取得されているように思えます。これはどうですか?

{
    'foo': ['a', 'c'],
    'bar': ['b', 'e'],
    'baz': ['d']
}

変換するのは簡単なはずです:

flippedObj = {};
for (var letter in obj) {
    if (obj.hasOwnProperty(letter)) {
        var letters = flippedObj[obj[letter]];
        if (letters === undefined) {
            letters = [];
            flippedObj[obj[letter]] = letters;
        }

        letters.push(letter);
    }
}

(脳内コンパイル; いくつかのエラーがある可能性があります。)

于 2011-01-07T09:23:05.640 に答える