3

My below code works perfectly, however I have hit a wall when I try and create a nested array to add more values to my 'item' property. I'm not sure how to incorporate this nested array with multiple items into my if statement. I'm able to capture a single index (the code I have now) ex. milk, will tell me that it's in aisle 1, but when I add multiple items in a created nested array ex. ["milk", "cheese", "eggs"], my code does nothing, it does not search through all items in the 'item' property. I would like to add multiple items to the each aisle. ex.

aisle: "Aisle 1",
item: ["milk", "cheese", "eggs"], 

aisle: "Aisle 2", 
item: ["lettuce", "tomatoes", "onions"],

If someone would be so kind to point me in the right direction or possible documentation on this matter. I have researched everywhere and I'm having a hard time finding material on nested arrays that involve both a for loop and an if statement.

End Goal: The user types in an item from the word bank form, and the application will let them know what aisle it is hiding in. I want to use Vanilla Javascript, I am not interested in jQuery. Yes, I'm a beginner.

<form>
  <input type="text" name="productName" value="" id ="input">
  <button type="button" value = "" onclick="start()" id ="">Click Me!</button>
</form>


<br>

<div class="jumbotron">
  <h2 class="display-4">Work Bank</h2>
  <p class="lead">Milk, Lettuce, Shampoo</p>
</div>


 function start(){
      var products = [
      {
        aisle: "Aisle 1",
        item: "milk",  
        onSale: false,
      },
      {
        aisle: "Aisle 2", 
        item: "lettuce", 
        onSale: true,
      },
      {
        aisle: "Aisle 3", 
        item: "shampoo",
        onSale: false,
      }
      ]

      for(i = 0; i < products.length; i++){
        if (products[i].item === document.getElementById('input').value){
          console.log("Your item " + '(' + products[i].item + ')'+ " is in " + products[i].aisle);
        }  
      } 
    }
2
  • 1
    Firstly, I believe you need to remove id ="input" from your button Commented Aug 4, 2018 at 19:27
  • Fixed it, nice catch. Commented Aug 4, 2018 at 19:29

7 Answers 7

2

I would consider a different data representation if you are going to be using it this way. Instead of an array of products, have an object of products where the product name is the key. This will allow fast access to what you want without having to loop through arrays.

For example:

var products = {
  milk: {
    aisle: 1,
    onSale: false,
  },
  lettuce: {
    aisle: 2,
    onSale: true,
  },
  shampoo: {
    aisle: 3,
    onSale: false,
  }
}
let someProd = 'lettuce' // or document.getElementById('input').value
if (someProd in products) {
  console.log("Your item " + '(' + someProd + ')' + " is in aisle " + products[someProd].aisle);
}

Now you can add as many items as you want without issue. After this, if you find you need to quickly see everything in a particular aisle, you can transform this into an aisles object keyed to aisle:

var products = {milk: {aisle: 1,onSale: false,},cheese: {aisle: 1,onSale: false,},yogurt: {aisle: 1,onSale: false,},lettuce: {aisle: 2, onSale: true,},shampoo: {aisle: 3, onSale: false,}}

// makes aisle
let aisles = Object.keys(products).reduce((a, product) => {
   let aisle = products[product].aisle
   if (!a[aisle]) a[aisle] = []
   a[aisle].push(product)
   return a
},{})

// what's in aisle 1?
console.log("aisle 1", aisles[1])
// 2?
console.log("aisle 2", aisles[2])

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Mark, I thought about doing it this way but wouldn't this mean I would have to make each item it's own object? That seemed like a substantial amount of code so I thought nesting them in an array would appear better.
@Alexandra, since each item has properties like on sale, they need to be individual objects anyway (and they're individual objects in your example). This just changes how they are stored -- in an object keyed to item name rather than an array keyed to some index. -- Of course there's more than one way to do this, so this might not be right for you.
Ah! You know Mark, I forgot about my property of 'onSale'. You are absolutely, right, they do have to have their own object due to that property.
0

Make array from all item properties and then just check for each element inside that array if it is equal to the input. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

  var products = [
  {
    aisle: "Aisle 1",
    item: ["milk", 'egg', 'tomato'],  
    onSale: false,
  },
  {
    aisle: "Aisle 2", 
    item: ["lettuce"], 
    onSale: true,
  },
  {
    aisle: "Aisle 3", 
    item: ["shampoo"],
    onSale: false,
  }
  ]

  for(i = 0; i < products.length; i++){
    products[i].item.forEach(el => {
        // console.log(el)
        if (el === 'milk'){
            console.log("Your item " + '(' + el + ')'+ " is in " + products[i].aisle);
          }  
    })

  } 

Comments

0

You're almost there! Your code:

for(i = 0; i < products.length; i++){
  if (products[i].item === document.getElementById('input').value){
    console.log("Your item " + '(' + products[i].item + ')'+ " is in " + products[i].aisle);
  }  
}

Works fine with a single item. Now, you need to search, instead of the item itself, in an array of items. This should work -if I didn't make any mistake :-D - :

function start(){
  var products = [
  {
    aisle: "Aisle 1",
    items: ["milk", "cheese", "eggs"],  
    onSale: false,
  },
  {
    aisle: "Aisle 2", 
    items: ["lettuce", "tomatoes", "onions"], 
    onSale: true,
  },
  {
    aisle: "Aisle 3", 
    items: ["shampoo", "bath salt", "shower gel"],
    onSale: false,
  }
  ]
  var userInput = document.getElementById('input').value;

  for(i = 0; i < products.length; i++){
    const currentAisle = products[i];
    const items = currentAisle.items;

    for(k =0; k < items.length; k++ ){
      if(items[k] === userInput){
        console.log("Your item " + '(' + items[k] + ')'+ " is in " + currentAisle.aisle);
      }
    }

  } 
}

Now, however, you asked for documentation about how to work with nested arrays. While I don't exactly know a good resource about that topic, there are several javascript array apis you should investigate (and the other answers use them, producing in fact better code than my answer):

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

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

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

https://medium.com/@joomiguelcunha/learn-map-filter-and-reduce-in-javascript-ea59009593c4

3 Comments

Thanks Sergeon! As I was continuing to think hard about this, I just though, "it may need another for loop..." lol. I tried your code and oddly I'm getting an error that it can't recognize 'length' in the second for loop? Oh, and thanks so much for the articles!
Maybe 'cause you didn't rename item for items?
That was it, thanks man. Also, I need to read up on 'const'. I don't believe I've seen those before.
0

I would suggest to use Array.prototype.some (if you can use ES6; if not we can rewrite it with plain for-loop):

var products = [
  {
    aisle: "Aisle 1",
    items: ["milk", "cheese", "eggs"],  
    onSale: false,
  },
  {
    aisle: "Aisle 2", 
    items: ["lettuce"], 
    onSale: true,
  },
  {
    aisle: "Aisle 3", 
    items: ["shampoo"],
    onSale: false,
  }
];
var input = document.getElementById('input');

function start(){
  for(i = 0; i < products.length; i++){
    if (products[i].items.some(value => value === input.value)) {
      console.log("Your item " + '(' + input.value + ')'+ " is in " + products[i].aisle);
    }  
  } 
}

Also, as you see, I moved data and DOM element initialization out from function declaration, it could be important from the performance view.

Comments

0

You could just do that with two loops, one goes over the objects, then the inner iterates over the items. Or you just find the object were the items includes the value:

 const search = document.getElementById('input').value
 const product = products.find(product => product.item.includes(search));
 console.log(product.aisle);

Comments

0

Here is an implementation it has slight variations from your code but should do the trick:

      var products = [
      {
        aisle: "Aisle 1",
        item: "milk",  
        onSale: false,
      },
      {
        aisle: "Aisle 2", 
        item: "lettuce", 
        onSale: true,
      },
      {
        aisle: "Aisle 3", 
        item: "shampoo",
        onSale: false,
      }
      ];

let h1 = document.getElementById('display');

function check () {
  let input = document.getElementById('textInput').value;
  for(let i = 0 ; i<products.length ; i++) {
    if(products[i].item === input) {
      h1.innerText = products[i].aisle
      return;
    } else {
      h1.innerText = 'Item not found in any Aisle'
    }
  }
}
<input type="text" id="textInput" oninput=check()>
<h1 id="display"></h1>

Now when we type milk it will show that it can be found in Aisle one.

Comments

0

You could utilize find/includes for this and then the logic becomes one liner really:

products.find((x) => x.items.includes(input))

var products = [{
    aisle: "Aisle 1",
    items: ["milk", "cheese", "eggs"],
    onSale: false,
  },
  {
    aisle: "Aisle 2",
    items: ["lettuce"],
    onSale: true,
  },
  {
    aisle: "Aisle 3",
    items: ["shampoo"],
    onSale: false,
  }
];

document.getElementById('startSearch').addEventListener('click', start)

function start(e) {
  var input = document.getElementById('inputBox').value
  var result = products.find((x) => x.items.includes(input)) || {}
  document.getElementById('result').innerText = result.aisle || 'Not Found!'
}
<input type="text" name="productName" value="" id="inputBox">
<button id="startSearch" type="button">Click Me!</button>

<br>
<div id="result" class="jumbotron"></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.