2016-11-02 4 views
2

私はidプロパティを使用してオブジェクトの配列を取得し、マップされたオブジェクトに変換するためにlodash mapKeysを使用しています。それは簡単ですが、問題は新しいオブジェクトをidでソートすることです。例えばlodash mapKeysが配列を並べ替えるのを防ぐには?

私は、アレイ内の3つのオブジェクトがあった場合:

let myArray = [ 
    { 
     id: 3, 
     name: 'Number Three' 
    }, 
    { 
     id: 1, 
     name: 'Number One' 
    }, 
    { 
     id: 2, 
     name: 'Number Two' 
    } 
]; 

その後、私はidでキーをマップ:

_.mapKeys(myArray, 'id') 

をそれは次の値を返します。

{ 
    1: { 
     id: 1, 
     name: 'Number One' 
    }, 
    2: { 
     id: 2, 
     name: 'Number Two' 
    }, 
    3: { 
     id: 3, 
     name: 'Number Three' 
    } 
} 

マイサーバーは配列を特定の順序で返します。オブジェクトを同じままにしたいのでオブジェクトのプロパティをループすると、正しい順序になります。

この方法で可能ですか?そうでない場合は、結果を達成するための代替手段がありますか?

+0

これは実際にネイティブのJavaScriptの動作です。 'var o = {}; o [3] = 3; o [1] = 1; 'o:' {1:1、3:3} 'なぜこれがあなたのために問題を引き起こしていますか?リスト全体を反復処理する場合、マップ形式では必要ありません。キーIDでオブジェクトにアクセスする場合は、順序は関係ありません。 –

+0

ああ、ソートせずにオブジェクトのプロパティを配置することはできませんか? –

+0

問題は並べ替えと更新の容易さに関連しています。配列を使用して表示するために配列をマップすることはできますが、大きな配列です。配列をループして正しいオブジェクトを見つけて更新するのではなく、 'object [property] = value'を使って更新する方がはるかに高速です。 –

答えて

0

コメントと同様に、順序を維持するためにオブジェクト参照を配列内に保持し、更新を容易にするためにハッシュで保持するのが最適です。

Backbone's collectionsource)はこのように動作します。オブジェクトを配列(models)に保持しますが、モデル(オブジェクト)の追加と削除、またはモデルのIDの変更時にハッシュ(_byId)を自動的に更新します。

ここでは、概念の簡単な実装について説明します。独自の実装を行うか、コレクションlibをチェックすることができます。

// a little setup 
 
var array = []; 
 
var hash = {}; 
 

 
var addObject = function addObject(obj) { 
 
    hash[obj.id] = obj; 
 
    array.push(obj); 
 
} 
 

 
// Create/insert the objects once 
 
addObject({ id: 3, name: 'Number Three' }); 
 
addObject({ id: 1, name: 'Number One' }); 
 
addObject({ id: 2, name: 'Number Two' }); 
 

 
// Easy access by id 
 
console.log("by id with hash", hash['1']); 
 

 
// updating is persistent with the object in the array 
 
hash['1'].name += " test"; 
 

 
// keeps the original ordering 
 
for (var i = 0; i < 3; ++i) { 
 
    console.log("iterating", i, array[i]); 
 
}

0

としては、順序を保証するものではありませんオブジェクトをループ、コメントで指摘しました。順序付きリストが必要な場合は、配列が必要です。

ただし、イテレータパターンを適用できます。このパターンでは、 "次の"要素が何であるかを決定するのはあなた次第です。したがって、オブジェクトを持つセット(一定の時間にそれらを取得するため)と、配列を格納する配列を持つことができます。反復するには、反復子を使用します。

このコードを例として使用できます。

希望します。

let myArray = [{ 
 
    id: 3, 
 
    name: 'Number Three' 
 
}, { 
 
    id: 1, 
 
    name: 'Number One' 
 
}, { 
 
    id: 2, 
 
    name: 'Number Two' 
 
}]; 
 

 
let myIterator = ((arr) => { 
 
    let mySet = _.mapKeys(arr, 'id'), 
 
    index = 0, 
 
    myOrder = _.map(arr, _.property('id')); 
 

 
    return { 
 
    getObjById: (id) => mySet[id], 
 
    next:() => mySet[myOrder[index++]], 
 
    hasNext:() => index < myOrder.length 
 
    }; 
 
})(myArray); 
 

 
// Access elements by id in constant time. 
 
console.log(myIterator.getObjById(1)); 
 

 
// Preserve the order that you got from your server. 
 
while (myIterator.hasNext()) { 
 
    console.log(myIterator.next()); 
 
}
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script>

0

あなたは直接のような項目を追加および削除することができますので、Mapを使用して:

繰り返し処理を行う場合、マップは ためという要素が挿入される順序と名誉を記録キー、値、またはエントリを含む。

const myArray = [ 
 
    { 
 
     id: 3, 
 
     name: 'Number Three' 
 
    }, 
 
    { 
 
     id: 1, 
 
     name: 'Number One' 
 
    }, 
 
    { 
 
     id: 2, 
 
     name: 'Number Two' 
 
    } 
 
]; 
 

 
const map = myArray.reduce((map, item) => map.set(item.id, item), new Map()); 
 

 
map.forEach((item) => console.log(item));

+0

[ブラウザのサポート](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Browser_compatibility)は異なる場合があります。 IE11でも 'Map'のすべての機能が実装されているわけではありません。 –

関連する問題