1

数値の配列があり、特定の x より小さい最初の数値を取得し、次に同じ x より大きい最初の数値を取得したいと考えています。

var str = 'some random string that is kind of long',
        items = [],
        position = 10, //varies
        itemsBefore,
        itemsAfter,
        firstItemBeforePosition,
        firstItemAfterPosition; //varies

for(var i = 0, length= str.length; i < length; i++){
    if(str[i] === ' '){
        items.push(i);
    }
}

itemsBefore = items.filter(function(item){
    return item < position;
});

itemsAfter = items.filter(function(item){
    return item > position;
});

firstItemBeforePosition = itemsBefore.length > 0 ? itemsBefore[itemsBefore.length - 1] : 0;
firstItemAfterPosition = itemsAfter.length > 0 ? itemsAfter[0] : str.length;

私が提供した JavaScript コードに基づいて、items 配列は[4, 11, 18, 23, 26, 31, 34]firstItemBeforePosition4、およびfirstItemAfterPosition11 になります。

これを行うより良い方法はありますか?

ありがとうございました。

4

2 に答える 2

2

必要なコードが少なく、リスト全体をループしない別の方法を次に示します。また、使用する変数が少なくなり、より多くのネイティブ コード関数が使用されます (より高速になるはずです)。

var str, array, length, firstItemBeforePosition, firstItemAfterPosition;

str = 'some random string that is kind of long';
length = 0;
position = 10;

array = str.split(' ');
array = array.map( function( s, i ){ length += s.length; return length+i })

array.some(function(e){
  if ( e < position ) firstItemBeforePosition = e;
  if ( e > position ) {
    firstItemAfterPosition = e;
  }
  return firstItemAfterPosition;
});

some 関数は 1.6 (ES5) の時点で Javascript にあり、IE9+ で動作します。for ループや forEach とは異なり、some メソッドは、コールバック関数が真の値を返すとすぐに戻ります。firstItemAfterPosition開始時に は null であるため、それは誤りであり、値を代入するまで続くものもあれば、それが真実である時間までに終了するものもあります。

位置値のリストが非常に長い場合は、O(n) ではなく O(log n) になるため、バイナリ検索を検討することをお勧めします。それが何を意味するのかわからない場合は、問題のサイズがおそらく十分に小さいため、心配する必要はありません:)

于 2013-11-13T09:02:34.307 に答える
1

単純なループでこれを行う必要があります。

for(var k = 0; k < items.length; k++)
{
  if (items[k] > position)
  {
    firstItemAfterPosition = items[k];
    firstItemBeforePosition = items[k-1];
    break;
  }
}

http://jsfiddle.net/7CZvf/1/

于 2013-11-13T09:03:07.797 に答える