Неверное возвращаемое значение для функции сравнения?

#javascript #arrays #function #comparison #operators

#javascript #массивы #функция #сравнение #операторы

Вопрос:

Функция expensiveItem(menu) должна возвращать самый дорогой элемент в массиве, питание. В этом случае он должен возвращать «Двойную четверть фунта с сыром». Вместо этого он возвращает «Двойной чизбургер». Где я ошибся в своем коде?

 var item1 = {
  name: "Big Mac",
  price: 3.99,
  calories: 530
};
var item2 = {
  name: "Filet-O-Fish",
  price: 3.79,
  calories: 390
};
var item3 = {
  name: "Double Cheeseburger",
  price: 1.59,
  calories: 430
};
var item4 = {
  name: "Double Quarter Pounder with Cheese",
  price: 4.79,
  calories: 740
};
var item5 = {
  name: "Chicken McNuggets",
  price: 4.49,
  calories: 190
};

var meals = [item1, item2, item3, item4, item5];


function init() {
  var lowestCost = document.getElementById('cheapestItem');

  lowestCost.onclick = function() {
    cheapestItem(meals);
  }

  var highestCost = document.getElementById('highestCost');

  highestCost.onclick = function() {
    expensiveItem(meals);
  }

}

window.onload = init;


// return name of cheapest item on menu
function cheapestItem(menu) {
  var msg = document.getElementById('msg1'); // is this necessary? Code works fine without it...

  var cheapestItem = operation(menu, "less");
  msg1.innerHTML = "The cheapest item is "   cheapestItem;
}

// return name of most expensive item on menu
function expensiveItem(menu) {
  var msg = document.getElementById('msg2');

  var expensiveItem = operation(menu, "greater");
  msg2.innerHTML = "The most expensive item is "   expensiveItem;
}

//return result based on given comparator operator
function operation(menu, op) {
  var v1 = menu[0].price;
  var item;

  for (var i = 0; i < menu.length; i  ) {
    var v2 = menu[i].price;


    if ((op == "less" amp;amp; (v2 < v1)) ||
      (op == "greater" amp;amp; (v2 > v1))) {
      result = v2;
      item = menu[i].name;
    }
  }
  console.log(item);
  return item;
}  
 <body>

  <input type="button" id="cheapestItem" value="Cheapest Item">
  </div>
  <p id="msg1">message 1</p>

  <input type="button" id="highestCost" value="Most Expensive Item">
  </div>
  <p id="msg2">message 2</p>
</body>  

Комментарии:

1. Просто побочный узел, вам нужно присвоить значение item var item = menu[0].name; , потому что он завершится неудачей, если первый элемент будет самым большим или самым маленьким, в зависимости от op .

Ответ №1:

Проблема здесь:

 if ((op == "less" amp;amp; (v2 < v1)) || (op == "greater" amp;amp; (v2 > v1)))
  

Вы только сравниваете v1 и v2 , но вы также должны присвоить v1 значение v2 , если условие выполнено.

Объяснение:

Ниже приведены значения в цикле

 3.99 3.99
3.99 3.79
3.99 1.59
3.99 4.79
4.79 4.49
  

Если вы заметили, последние 2 операции удовлетворяют условию. Таким образом, вы получите последнее.

 var item1 = {
  name: "Big Mac",
  price: 3.99,
  calories: 530
};
var item2 = {
  name: "Filet-O-Fish",
  price: 3.79,
  calories: 390
};
var item3 = {
  name: "Double Cheeseburger",
  price: 1.59,
  calories: 430
};
var item4 = {
  name: "Double Quarter Pounder with Cheese",
  price: 4.79,
  calories: 740
};
var item5 = {
  name: "Chicken McNuggets",
  price: 4.49,
  calories: 190
};

var meals = [item1, item2, item3, item4, item5];


function init() {
  var lowestCost = document.getElementById('cheapestItem');

  lowestCost.onclick = function() {
    cheapestItem(meals);
  }

  var highestCost = document.getElementById('highestCost');

  highestCost.onclick = function() {
    expensiveItem(meals);
  }

}

window.onload = init;


// return name of cheapest item on menu
function cheapestItem(menu) {
  var msg = document.getElementById('msg1'); // is this necessary? Code works fine without it...

  var cheapestItem = operation(menu, "less");
  msg1.innerHTML = "The cheapest item is "   cheapestItem;
}

// return name of most expensive item on menu
function expensiveItem(menu) {
  var msg = document.getElementById('msg2');

  var expensiveItem = operation(menu, "greater");
  msg2.innerHTML = "The most expensive item is "   expensiveItem;
}

//return result based on given comparator operator
function operation(menu, op) {
  var v1 = menu[0].price;
  var item;

  for (var i = 0; i < menu.length; i  ) {
    var v2 = menu[i].price;

    if ((op == "less" amp;amp; (v2 <= v1)) ||
      (op == "greater" amp;amp; (v2 >= v1))) {
      result = v1 = v2;
      item = menu[i].name;
    }
  }
  console.log(item);
  return item;
}  
 <body>

  <input type="button" id="cheapestItem" value="Cheapest Item">
  </div>
  <p id="msg1">message 1</p>

  <input type="button" id="highestCost" value="Most Expensive Item">
  </div>
  <p id="msg2">message 2</p>
</body>  

Альтернативный способ

Отсортируйте свой массив init . Теперь вам не нужно выполнять цикл, чтобы получить минимальные и максимальные значения.

Примечание: его плохая практика использования window.load = function , вы должны использовать window.addEventListener('load', function) вместо

 var item1 = {
  name: "Big Mac",
  price: 3.99,
  calories: 530
};
var item2 = {
  name: "Filet-O-Fish",
  price: 3.79,
  calories: 390
};
var item3 = {
  name: "Double Cheeseburger",
  price: 1.59,
  calories: 430
};
var item4 = {
  name: "Double Quarter Pounder with Cheese",
  price: 4.79,
  calories: 740
};
var item5 = {
  name: "Chicken McNuggets",
  price: 4.49,
  calories: 190
};

var meals = [item1, item2, item3, item4, item5];
var OP_LESS = "less";
var OP_GREATER = "greater";

function init() {
  var lowestCost = document.getElementById('cheapestItem');

  lowestCost.onclick = function() {
    cheapestItem(meals);
  }

  var highestCost = document.getElementById('highestCost');

  highestCost.onclick = function() {
    expensiveItem(meals);
  }
  sortData();
}

function sortData(){
  meals.sort(function(a,b){
    return a.price > b.price ? 1 : a.price < b.price ? -1 : 0
  });
}

window.addEventListener('load', init);

// return name of cheapest item on menu
function cheapestItem(menu) {
  var msg = document.getElementById('msg1'); // is this necessary? Code works fine without it...

  var cheapestItem = operation(menu, OP_LESS);
  msg1.innerHTML = "The cheapest item is "   cheapestItem;
}

// return name of most expensive item on menu
function expensiveItem(menu) {
  var msg = document.getElementById('msg2');
  var expensiveItem = operation(menu, OP_GREATER);
  msg2.innerHTML = "The most expensive item is "   expensiveItem;
}

//return result based on given comparator operator
function operation(menu, op) {
  return (op === OP_LESS ? meals[0] : meals[meals.length-1]).name
}  
 <body>

  <input type="button" id="cheapestItem" value="Cheapest Item">
  </div>
  <p id="msg1">message 1</p>

  <input type="button" id="highestCost" value="Most Expensive Item">
  </div>
  <p id="msg2">message 2</p>
</body>  

Комментарии:

1. ооо, я изменил имена переменных, но никогда не менял «результат» на «v1». Спасибо, хороший улов! 🙂

Ответ №2:

Вы всегда сравниваете с начальным значением v1, когда вы находите «большее», вы должны установить новое значение var v1.

 if ((op == "less" amp;amp; (v2 < v1)) ||
    (op == "greater" amp;amp; (v2 > v1))) {
    result = v2;
    v1=v2; //Set new greater/lower value
    item = menu[i].name;
}
  

Комментарии:

1. Да, теперь я вижу, я изменил имена переменных, но никогда не менял «результат» на «v1». Спасибо! 🙂

Ответ №3:

Я предлагаю использовать только одну переменную для проверки и возврата

 function operation(menu, op) {
    var price = menu[0].price,
        item = menu[0].name;

    for (var i = 0; i < menu.length; i  ) {
        if (
            op === "less"    amp;amp; menu[i].price < price ||
            op === "greater" amp;amp; menu[i].price > price
        ) {
            price = menu[i].price;
            item = menu[i].name;
        }
    }
    console.log(item);
    return item;
}
  

 var item1 = {      name: "Big Mac",      price: 3.99,      calories: 530    };
var item2 = {      name: "Filet-O-Fish",      price: 3.79,      calories: 390    };
var item3 = {      name: "Double Cheeseburger",      price: 1.59,      calories: 430    };
var item4 = {      name: "Double Quarter Pounder with Cheese",      price: 4.79,      calories: 740
};
var item5 = {      name: "Chicken McNuggets",      price: 4.49,      calories: 190    };

var meals = [item1, item2, item3, item4, item5];

function init() {
  var lowestCost = document.getElementById('cheapestItem');
  lowestCost.onclick = function() {
    cheapestItem(meals);
  }

  var highestCost = document.getElementById('highestCost');

  highestCost.onclick = function() {
    expensiveItem(meals);
  }
}

window.onload = init;

// return name of cheapest item on menu
function cheapestItem(menu) {
  var msg = document.getElementById('msg1'); // is this necessary? Code works fine without it...

  var cheapestItem = operation(menu, "less");
  msg1.innerHTML = "The cheapest item is "   cheapestItem;
}

// return name of most expensive item on menu
function expensiveItem(menu) {
  var msg = document.getElementById('msg2');

  var expensiveItem = operation(menu, "greater");
  msg2.innerHTML = "The most expensive item is "   expensiveItem;
}

//return result based on given comparator operator
function operation(menu, op) {
  var price = menu[0].price,
      item = menu[0].name;

  for (var i = 0; i < menu.length; i  ) {
    if (op == "less" amp;amp; menu[i].price < price || op == "greater" amp;amp; menu[i].price > price) {
      price = menu[i].price;
      item = menu[i].name;
    }
  }
  console.log(item);
  return item;
}  
   <input type="button" id="cheapestItem" value="Cheapest Item">
  <p id="msg1">message 1</p>
  <input type="button" id="highestCost" value="Most Expensive Item">
  <p id="msg2">message 2</p>  

Комментарии:

1. Привет, Нина, есть ли причина, по которой вы это предлагаете? Я думал, что присвоение переменной ‘menu [i].price’ сделает код более чистым и сделает его менее избыточным. Но, может быть, это не имеет большого значения?

2. еще один шаг, я бы взял только индекс меню, который является минимальным или максимальным. только для возврата значения я бы вернул имя menu[index] . причина использования только одного параметра vsariable заключается в том, чтобы всегда сохранять его равным приличному значению. если вы используете две переменные, вы можете перепутать контекст переменных.