2017-12-22 11 views
3

を探します。言い換えるのは、JSに我々はイベントオブジェクトの次の配列を持っていると仮定してみましょう:私は、配列の<strong>キー</strong>がイベントの<em>のUnixタイムスタンプ</em>ある「<em>イベント</em>」の配列を扱っています最も近い配列のインデックス

var MyEventsArray=[]; 
MyEventsArray[1513957775]={lat:40.671978333333, lng:14.778661666667, eventcode:46}; 
MyEventsArray[1513957845]={lat:40.674568332333, lng:14.568661645667, eventcode:23}; 
MyEventsArray[1513957932]={lat:41.674568332333, lng:13.568661645667, eventcode:133}; 
and so on for thousands rows... 

データはアヤックスコールに沿って送信され、JSで処理するJSONでエンコードされています。データセットが受信されると、別のUnix Timestampが別のソースから来て1513957845と言って、その時に起こったイベントを見つけたいと思っています...それはかなり簡単です。指定されたインデックス(上記のリストの2番目のインデックス)。 質問:特定のインデックスが見つからないことを想像してください(私たちはUXTimestamp = 1513957855を探しています)、このインデックスは配列には存在しませんでしたが、は最も近いインデックスをとります要素MyEventsArray [1513957845]を取得します(インデックス1513957845は1513957855に最も近い)。この結果を得るために私は何ができますか? 配列を受け取ったときに配列インデックスを扱うのが難しいです。インデックスの開始位置がわかりません。

どのようにマシンがそのような状況を処理するのですか? マシンは、各行の間に置かれたダミー/空の要素のためにメモリを割り当て(そして無駄に)使用しますか、コンパイラはそれ自身のインデックスを構築して領域を最適化する何らかの能力を持っていますか?言い換えれば、私たちがやっているようインデックスで再生するには、それが安全であるか、として配列を割り当てる方が良いでしょう:

この場合
var MyEventsArray=[]; 
MyEventsArray['1513957775']={lat:40.671978333333, lng:14.778661666667, eventcode:46}; 
MyEventsArray['1513957845']={lat:40.674568332333, lng:14.568661645667, eventcode:23}; 
MyEventsArray['1513957932']={lat:41.674568332333, lng:13.568661645667, eventcode:133}; 
and so on for thousands rows... 

キーとインデックスが明確にそれを取得することが可能ですので、ここで異なっています私たちがキー値を知らないにもかかわらず、最初の要素はMyArray [0]です。この方法はメモリの面でより高価です(ここではインデックスとキーを保存する必要があります)か、エフェクトはコンパイラで同じですか?

答えて

3

MyEventsArray[1513957775]MyEventsArray['1513957775']の間に違いはありません。深いところでは、配列インデックスは単にプロパティ名であり、プロパティ名は文字列です。

これらの疎指数が何百万という空のセルが割り当てられるかどうかという疑問については、それは起こりません。スパース配列は、空のスペースではなく、あなたが入れたものだけを格納します。

すばやくキーを検索したい場合は、キーの配列を得ることができ、それらを並べ替え、次にあなたが欲しい1見つける:

var MyEventsArray=[]; 
 
MyEventsArray[1513957775]={lat:40.671978333333, lng:14.778661666667, eventcode:46}; 
 
MyEventsArray[1513957845]={lat:40.674568332333, lng:14.568661645667, eventcode:23}; 
 
MyEventsArray[1513957932]={lat:41.674568332333, lng:13.568661645667, eventcode:133}; 
 

 
var target = 1513957855; 
 

 
var closest= Object.keys(MyEventsArray) 
 
        .map(k => ({ k, delta: Math.abs(target - k) })) 
 
        .sort((a, b) => a.delta - b.delta)[0].k; 
 

 
console.log(closest);

+0

賢い解決策、私はObject.keys()を過小評価しました。それはまさに私が探していたものです。 –

0

Object.keys(MyEventsArray)を使用すると、キーの配列(文字列として不思議な表現)を取得できます。あなたはそれを繰り返して、最も近いものを見つけることができます。

var MyEventsArray=[]; 
MyEventsArray[1513957775]={lat:40.671978333333, lng:14.778661666667, eventcode:46}; 
MyEventsArray[1513957845]={lat:40.674568332333, lng:14.568661645667, eventcode:23}; 
MyEventsArray[1513957932]={lat:41.674568332333, lng:13.568661645667, eventcode:133}; 
Object.keys(MyEventsArray) 

["1513957775", "1513957845", "1513957932"]

参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

+0

ニース - あなたは、キー配列の値と検索値の差の絶対値からなる各エントリに2つ目のプロパティを追加し、そのキー配列に対して '.map' ..その後、ソート可能性最初のエントリを取得している昇順の差によって返されたマップされた配列..私はこの 'Object.keys(MyEventsArray)'が好きです。 – Forty3

0

をあなたが疎で使用していますデータを格納する配列。スパース配列は余分なメモリを消費しないので、それに問題はありません(discussed here)。

var MyEventsArray = []; 
 
MyEventsArray[1513957775] = { lat: 40.671978333333, lng: 14.778661666667, eventcode: 46 }; 
 
MyEventsArray[1513957845] = { lat: 40.674568332333, lng: 14.568661645667, eventcode: 23 }; 
 
MyEventsArray[1513957932] = { lat: 41.674568332333, lng: 13.568661645667, eventcode: 133 }; 
 

 
var tests = [1513957765, 1513957775, 1513957810, 1513957811, 1513957932, 1513957942]; 
 
tests.forEach(function(search) { 
 
    var closest = Object.keys(MyEventsArray).reduce(function(best, curr) { 
 
    return Math.abs(search - curr) < Math.abs(search - best) ? curr : best; 
 
    }); 
 
    console.log("search = %d, closest = %s, delta = %d", search, closest, search - closest); 
 
});

+0

_ "Object.keysは数字キーを昇順に並べ替える" _の引用をしていますか? – JLRishe

+0

@ JLRishe for ES6、はい:[Object.keys](https://www.ecma-international.org/ecma-262/6.0/#sec-object.keys) - > [EnumerableOwnNames](https:// www .ecma-international.org/ecma-262/6.0 /#sec-enumerableownnames)(手順6)→[列挙](https://www.ecma-international.org/ecma-262/6.0/#sec-ordinary -object-internal-methods-and-internal-slots-enumerate) - > [OwnPropertyKeys](https://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods- and-internal-slots-ownpropertykeys) - > _整数インデックスであるOのそれぞれのプロパティキーPについて、昇順の数値インデックスorder_ –

+0

で@JLRisheは答えを元に戻しました。 「for ... in」は同じ問題、注文のもの、「for ... of」は遅すぎます。 –

1

あなたはデルタがあれば、反復を終了するallowes Array#someを取ることができる:

値のリストから、正確なまたは最も近いものを見つけるには、一度反復しArray.reduceを使用することができます最後のデルタよりも大きくなっています。

var array = []; 
 
array[1513957775] = { lat: 40.671978333333, lng: 14.778661666667, eventcode: 46 }; 
 
array[1513957845] = { lat: 40.674568332333, lng: 14.568661645667, eventcode: 23 }; 
 
array[1513957932] = { lat: 41.674568332333, lng: 13.568661645667, eventcode: 133 }; 
 

 
var key = 0, 
 
    search = 1513957855; 
 

 
Object.keys(array).some(function (k) { 
 
    if (Math.abs(k - search) > Math.abs(key - search)) { 
 
     return true; 
 
    } 
 
    key = k; 
 
}); 
 

 
console.log(key);

+0

'Object.keys'は特定の順序でキーを返すことは保証されていないため、この最適化は実装の詳細に依存します。 – JLRishe

+0

@JLRishe、leaset ES2015の新しいシステムでは、整数プロパティが最初にソートされるので、ソートは必要ありません。イテレーションの正しい順序で取得するためです。バイナリ検索を使用することがより速いメッホードになる可能性があります。 –

+0

ありがとうございます。私は彼らがES2015でそれを標準化したことを認識しませんでした。 – JLRishe

関連する問題