2012-03-15 7 views
0

が、私はこのようになり、テーブルの列を持っている値:私はテーブルの列と列名の配列を受け取り、作る機能を作成しようとしているはJavaScript:列でオブジェクトを索引付けすることは

tablearray = 
[ 
    {'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2}, 
    {'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4}, 
    {'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6} 
] 

列値によって索引付けされる新しいオブジェクト。そう

newObject = indexByColumnValues(tablearray, ['column1', 'column2']); 

そこで

newObject = 
{ 
    1: 
     { 
      1: {'column1': 1, 'column2': 1, 'column3': 1, 'column4': 2}, 
      2: {'column1': 1, 'column2': 2, 'column3': 3, 'column4': 4} 
     } 
    2: 
     { 
      0: {'column1': 2, 'column2': 0, 'column3': 4, 'column4': 6} 
     } 
} 

newObject[1][1]['column3'] = 1 
newObject[1][2]['column4'] = 4 
etc... 

ようにオブジェクトをもたらすべきである場合、列名配列内の列の数(上記[ 'COLUMN1'、 'C​​OLUMN2'] )が知られている場合、その解決策は難しくありません。私はこの配列内の列名の任意の数を可能なら、それはここに1つの試みである不定再帰

newObject[tablearray[columnNameArray[0]][tablearray[columnNameArray[1]][tablearray[columnNameArray[2]]... 

があるように、より困難になります。私はポインタを使ってnewObject配列の次元の深さを指し示そうとしました。まず、pointer = newObjectです。次に、ポインタ= newObject [... [0]]。次に、point = newObject [... [0]] [... [1]]。等々。これはオブジェクトを適切に構築しますが、newObject [... [0]] ... [... [k]]に値を代入する方法はありません。

function indexByColumnValues(object, columnNameArray) 
{ 
    var newObject = {}; 

    for(i in object) 
    { 
     var index=[]; 

     for(j in columnNameArray) 
     { 
      index.push(object[i][columnNameArray[j]]); 
     } 

     var pointer = newObject; 

     for(j in index) 
     { 
      if(pointer[index[j]] == undefined) 
      { 
       pointer[index[j]] = {}; 
      } 

      pointer = pointer[index[j]]; 
     } 

     //now pointer points to newObject[index[0]][index[1]]...[index[k]] 
     //but I need to set newObject[...] above to be object[i]. How? 
     //pointer = object[i]; //won't work 
    } 

    return newObject; 
} 

ここで役立つヘルプやヒントがあります。ありがとう。

+0

私はあなたがライブラリを使用するか(非常に便利です)独自のコードから学びたいしたいかどうかわかりませんunderscore.jsには '_.groupBy'があります。 – pimvdb

+1

結果の内部オブジェクトは、一致する列の値が1つの各オブジェクトを保持する配列であるべきではありませんか? – jfriend00

+0

@ jfriend00私の目的として、私が使用することを期待している列の値の組み合わせが一意であるため、内部の配列は不要です。 –

答えて

1

あなたは再帰について言及しますが、あなたのコードでは使用しません。これは再帰が適切なツールである古典的な状況です。ここでは一つの実施です:

function indexByColumnValues(table, cols) { 
    // get the column we're indexing 
    var col = cols[0], 
     index = {}, 
     x, val; 
    // find all values 
    for (x=0; x<table.length; x++) { 
     val = table[x][col]; 
     // add to index if necessary 
     if (!index[val]) index[val] = []; 
     // push this row 
     index[val].push(table[x]); 
    } 
    // recurse if necessary 
    if (cols.length > 1) { 
     for (x in index) { 
      if (index.hasOwnProperty(x)) { 
       // pass the filtered table and the next column 
       index[x] = indexByColumnValues(
        index[x], 
        cols.slice(1) 
       ); 
      }     
     } 
    } 
    return index; 
} 

注@ jfriend00ノートとして、あなたが一致する行の配列ではなく、単一のオブジェクトであるためにあなたのインデックスの「葉」を望む、 - それは単なる偶然だというあなたの例では、あなただけ与えられたデータと列のセットに一致する行が1つあります。使用法:

indexByColumnValues(tablearray, ['column1','column2']);​ 

出力:

{ 
    "1":{ 
     "1":[ 
      {"column1":1,"column2":1,"column3":1,"column4":2} 
     ], 
     "2":[ 

      {"column1":1,"column2":2,"column3":3,"column4":4} 
     ] 
    }, 
    "2":{ 
     "0":[ 
      {"column1":2,"column2":0,"column3":4,"column4":6} 
     ] 
    } 
} 

JsFiddle:http://jsfiddle.net/RRcRM/3/

+0

これは美しく動作します。ありがとうございました。私はそれを必要以上に困難にしていた。再帰関数を使用することは間違いなく役立ちます。 –