开发者

Given an Index, Return a range of Values from an Array

First, apologies,this should be simple but I've had too much coffee and cannot wrap my tired brain around this (at least not without making it way more complicated than I know it should be).

Lets say I have a simple Javascript array with a number of items in it:

var items = ["Hello", "This", "is", "an", "array", "with", 
             "a", "number", "of", "items", "in", "it"];

For whatever reason I'm suddenly interested in the 2nd value:

items[1]
//-> "This"

But I also want to get the previous value, and the next two values…

//-> "Hello", "This", "is", "an"

To put it this way:

function getBatch(items, start) {
  // What goes here so it would return the results below?
}

g开发者_如何学PythonetBatch(items, 0);
//-> ["it", "Hello", "This", "is"]

getBatch(items, 4);
//-> ["an", "array", "with", "a"]

getBatch(items, (items.length-1));
//-> ["in" "it", "Hello", "This"]

What is the code for the function getBatch (above) in order to return those result-sets?

Please, no answers dependent on JQuery :)


Well, obviously the naive first step would be to simply write

return items.slice(start - 1, start + 2)

However this isn't going to work with the wrapping that you require. One approach that should work is a helper function that effectively makes the array circular on both edges:

function getElementAtIndex(items, idx) {
    // Normalise the index to an element in the actual range
    while (idx > items.length - 1)
    {
        idx -= items.length;
    }
    while (idx < 0)
    {
        idx += items.length;
    }

    return items[idx];
}

Then you can simply manually return the four elements surrounding your index like so:

function getBatch(items, start) {
   return [ getElementAtIndex(items, start - 1),
            getElementAtIndex(items, start),
            getElementAtIndex(items, start + 1),
            getElementAtIndex(items, start + 2)];
}

This approach is shown working here.

This probably isn't the most efficient or elegant approach, but it's fairly straightforward to understand and implement, so it might end up being the most practical if this code isn't in a performance hotspot.


Edited: (removed original version, as it was more crap than this)

function getBatch(items, start) {
  var tmpArr = items;
  tmpArr.splice(0,0,items);

  var offset = (start > items.length-3) ? 0 : items.length;

  return tmpArr.slice(start+offset-1,start+offset+3);
}

Edit 2.1 (bugfixed)

Edit 2.2 (move start to actual start and eliminate one wrap case (final)

Ok, crying boy cared for by his mother. Now, let's do this correct.

function getBatch(items, start) {
  // Behaviour not defined by example
  if(items.length < 4)
    return items;

  // Set start to actual start (start-1), and
  // ensure that start is always within 0 - items.length
  start = ((start-1)+items.length) % items.length;

  // First take care of the easy case.
  if(start < items.length-3) return items.slice(start,start+4);

  // Last x elements + (4-x) elements from beginning of array
  return items.slice(start).concat(items.slice(0,4-(items.length-start)));
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜