39

I am trying to make a JavaScript function that will search an array of strings for a value and return the next string. For example, if an array is built such that an item is followed by its stock code, I want to search for the item and have the stock code written.

var item = (from user input); //some code to get the initial item from user
function findcode(code){
  var arr = ["ball", "1f7g", "spoon", "2c8d", "pen", "9c3c"]; //making the array
  for (var i=0; i<arr.lenth; i++){  //for loop to look through array
    arr.indexOf(item);  //search array for whatever the user input was
    var code = arr(i+1); //make the variable 'code' whatever comes next
    break;
  }
}
document.write(code); //write the code, I.e., whatever comes after the item

(I'm sure it's obvious I'm new to JavaScript, and while this is similar to a number of other questions I found, those seemed to have more involved arrays or more complex searches. I can't seem to simplify them for my needs.)

7 Answers 7

73

You've almost got it right, but the syntax is arr[x], not arr(x):

index = array.indexOf(value);
if(index >= 0 && index < array.length - 1)
   nextItem = array[index + 1]

BTW, using an object instead of an array might be a better option:

data = {"ball":"1f7g", "spoon":"2c8d", "pen":"9c3c"}

and then simply

code = data[name]
Sign up to request clarification or add additional context in comments.

5 Comments

+1 Just to add, Array.indexOf is ES5 and won't work on older browsers.
@thg435 Thanks so much! This is exactly what I needed. And thanks, too, for the object alternative.
Simple and useful, is Obviously conditions for previous Item must be (index > 0 && index < array.length) :-)
In regards to using an object instead of an array, it works well if the user types "ball" - it returns "1f7g". But if the user searches for "1f7g" nothing is returned since the key doesn't exist in the data object.
needs to cover if index cannot be found ... e.g. if index === -1
62

Cycled items from array this might be useful

const currentIndex = items.indexOf(currentItem);
const nextIndex = (currentIndex + 1) % items.length;
items[nextIndex];

The first item will be taken from the beginning of the array after the last item

4 Comments

Love the % items.length trick for cycling - nice and clean.
shorter: const nextIndex = ++currentIndex % items.length
I love it. Simple and clean.
For previous item, you can use (items.length + currentIndex - 1) % items.length
2

Try this String.prototype function:

String.prototype.cycle = function(arr) {
  const i = arr.indexOf(this.toString())
  if (i === -1) return undefined
  return arr[(i + 1) % arr.length];
};

Here is how you use it:

"a".cycle(["a", "b", "c"]); // "b"
"b".cycle(["a", "b", "c"]); // "c"
"c".cycle(["a", "b", "c"]); // "a"
"item1".cycle(["item1", "item2", "item3"]) // "item2"

If you want to do it the other way round, you can use this Array.prototype function:

Array.prototype.cycle = function(str) {
  const i = this.indexOf(str);
  if (i === -1) return undefined;
  return this[(i + 1) % this.length];
};

Here is how you use it:

["a", "b", "c"].cycle("a"); // "b"
["a", "b", "c"].cycle("b"); // "c"
["a", "b", "c"].cycle("c"); // "a"
["item1", "item2", "item3"].cycle("item1") // "item2"

Comments

1

I think that an object could be probably a better data structure for this kind of task

items = {
  ball : "1f7g",
  spoon: "2c8d", 
  pen  : "9c3c"
}


console.log(items['ball']); // 1f7g

1 Comment

+1 i wonder if the OP knew this behaviour is hash/associative array?
1

Here is an example as a one-liner to get the prev/next element in the array (returns null if element does not exist in the array):

var arr = [1, 2, 3];
var current = 3;

var next = arr.includes(current) ? arr[(arr.indexOf(current) + 1) % arr.length] : null;

console.log(next) // output: 1

var prev = arr.includes(current) ? [...arr.reverse()][(arr.indexOf(current) + 1) % arr.length] : null;

console.log(prev) // output: 2

Comments

0

You may pass array to function as argument and return found value from function:

var item = "spoon"; // from user input
var arr = ["ball", "1f7g", "spoon", "2c8d", "pen", "9c3c"]; //making the array
function findcode(item, arr){
    var idx = arr.indexOf(item);  //search array for whatever the user input was
    if(idx >=0 && idx <= arr.length - 2) { // check index is in array bounds
        return arr[i+1]; // return whatever comes next to item
    }
    return '';
}
document.write(findcode(item, arr)); //write the code, i.e., whatever comes after the item

Comments

0

Answer for 2022

This question came up when I was searching for a modern way to do this. I had been using the technique described in SerzN1's excellent answer without the wraparound (because I don't want that to happen). It winds up being quite a bit of code to make it safe, so I wanted something more modern.

As it turns out, there is a feature that has been available in every major browser since 2016. If someone hasn't updated their browser in six years, that's their loss, right?

ES2015 Array.find()

This function is used for finding a specific element in an array. That's exactly what we want to do here. The only problem is it doesn't maintain state for you, so you can only find a matching element, not the one after (or before, for that matter). To get around that, we use a closure.

Here's the short version:

let trigger = false;
const found = arr.find(element => trigger || (trigger = element === value) && !trigger);

You start with trigger set to false because we need to keep track of when the element is found (if at all). Then we use the Array.find() on the list we should be searching. The single argument to that function is a search function, which we define in-line as a closure so it has access to trigger.

The search function is the tricky part: element => trigger || (trigger = element === query.value) && !trigger. It might be easier to read if I break it apart into a more conventional function just so we can evaluate it. I'll describe what's happening in the comments:

function (element) {
  // If trigger is true, that means the previously-evaluated element was the match.
  // Therefore, we must be currently evaluating one AFTER it.
  // We should match on this one.
  if (trigger === true) return true;
  // Then we update the value of trigger to the result of comparing the element with the search value
  trigger = (element === value)
  // Now we `and` it together with its negation in order to make sure
  // it always returns false even when the element matches the search value
  return trigger && !trigger
}

And there you have it! It only takes two lines of code to get the element after one that matches your query.

Want to see it in action? Here you go:

function showNext() {
  const query = document.getElementById('query');
  if (query === null) return;
  const result = document.getElementById('result');
  if (result === null) return;
   var arr = ["ball", "1f7g", "spoon", "2c8d", "pen", "9c3c"];
  
  // This is the important part
  // Create a boolean flag that will inform the find function when it passes
  // the matching element in its search
  let trigger = false;
  const found = arr.find(element => trigger || (trigger = element === query.value) && !trigger);

  // Now `found` is equal to the array element AFTER the one you searched for
  // If it is undefined, that means the one you searched for was either the last
  // element in the array or it was missing.
  result.innerText = `Found ${found ?? 'nothing'}`;
}
<input id="query" />
<input type="submit" value="Display next" onclick="showNext()" />
<div id="result"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.