给定索引,从数组返回一系列值

时间:2021-10-19 16:41:13

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:

假设我有一个简单的Javascript数组,其中包含许多项:

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?
}

getBatch(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?

函数getBatch(上面)的代码是什么,以便返回这些结果集?

Please, no answers dependent on JQuery :)

请,没有答案依赖于JQuery :)

2 个解决方案

#1


1  

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)

编辑2.1(bugfixed)

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

编辑2.2(移动开始到实际开始并消除一个包裹案例(最终)

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)));
}

#2


3  

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.

这可能不是最有效或最优雅的方法,但理解和实现起来相当简单,因此如果此代码不在性能热点中,它可能最终变得最实用。

#1


1  

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)

编辑2.1(bugfixed)

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

编辑2.2(移动开始到实际开始并消除一个包裹案例(最终)

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)));
}

#2


3  

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.

这可能不是最有效或最优雅的方法,但理解和实现起来相当简单,因此如果此代码不在性能热点中,它可能最终变得最实用。