从下拉菜单(Javascript)输出两个数组值的差异



我有一个食品营养成分数组的数据库。我要做的只是让选择 2 个项目的结果是第一个项目和第二个项目的值之间的差异。例如,如果第一项是 72 卡路里,另一项是 50 卡路里,我希望输出说"多 22 卡路里、x 多克蛋白质、y 多克脂肪等"。如果项目颠倒过来,我希望它说少 22 卡路里,依此类推。

这是我到目前为止的代码。我能够输出每个项目的值,但还没有弄清楚如何输出差异:

var stocks = [
["Beef (80/20) raw","oz",72,4.85,5.65,0,2.142,19,20,4],
["Beef (90/10) raw","oz",50,5.65,2.83,0,1.109,19,18,4]]

$(".selectStock").each(function (){
for (var i = 0, len = stocks.length; i < len; i++) {
$("<option>").html(stocks[i][0]).attr("value", i).appendTo(this);
}
});
function r2d (i) {
return Math.round(i * 100) / 100
}
$(".selectStock").change(updateAmount);
$("#numberOfStocks").on('keyup', updateAmount);
function updateAmount() {
$(".selectStock").each(function () {
index = Number($(this).val());
if (isNaN(index)) {
return;
}
amt = Number($("#numberOfStocks").val());
if (isNaN(amt) || amt == 0) {
amt = stocks[index][9];
}
$(this).nextAll(".result:first").html("")
.append((r2d(amt*stocks[index][2])).toLocaleString() + " calories<br />")
.append((Math.round(stocks[index][3] * amt * 100)/100).toLocaleString() + " g of protein<br />")
.append((Math.round(stocks[index][4] * amt * 1000)/1000).toLocaleString() + " g of fat <br />")
.append((Math.round(stocks[index][5] * amt * 100)/100).toLocaleString() + " g of saturated fat <br />")
.append((Math.round(stocks[index][6] * amt * 100)/100).toLocaleString() + " g of sugar <br />")
.append((Math.round(stocks[index][7] * amt * 100)/100).toLocaleString() + " mg of sodium <br />")
.append((Math.round(stocks[index][8] * amt * 100)/100).toLocaleString() + " mg of cholesterol <br />");
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<meta name="viewport" content="width=10px, initial-scale=1.0">
</head>
<body>
<input value = "" type="text" id="numberOfStocks" />
<div style="display:block;">
<div class="side">
<h2>ounce of: </h2>
<select class="selectStock">
<option>Pick a food!</option>
</select>
<br>
<br>
<div class="result"></div>
</div>
<div class="side">
<h2>vs ounce of:</h2>
<select class="selectStock">
<option>Pick a food!</option>
</select>
<br>
<br>
<div class="result"></div>
</div>
</div>
</body>

将不胜感激对此的指导。谢谢一堆!

我玩了一下你的代码,并设法想出了一个解决方案。我添加的逻辑有点复杂,所以如果您有任何问题,请告诉我。我可能会稍后回来修改我编写的代码,使其更清晰一些。我尽力不更改您的原始stocks数据结构,因为看起来您正在接收该格式的数据,但是如果您可以更改它,我建议您这样做,因为stock[17]stock[4]没有任何语义。

var stocks = [
["Beef (80/20) raw", "oz", 72, 4.85, 5.65, 0, 2.142, 19, 20, 1],
["Beef (90/10) raw", "oz", 50, 5.65, 2.83, 0, 1.109, 19, 18, 1],
["Milk", "fl oz", 10, 1.46, 0.45, 0, 1.944, 10, 13, 8] // Made up values
]
function Stock (data) {
return {
name: data[0],
servingUnit: data[1],
calories: [data[2], ''],
protein: [data[3], 'g'],
fat: [data[4], 'g'],
saturatedFat: [data[5], 'g'],
sugar: [data[6], 'g'],
sodium: [data[7], 'mg'],
cholesterol: [data[8], 'mg'],
unitsPerServing: data[data.length - 1]
}
}
stocks = stocks.map(Stock)
var $selects = $('.selectStock')
var $quantity = $('#numberOfStocks')
var $comparisonResult = $('.comparison .result')
$selects.each(function() {
$(this).append(stocks.map(function(stock, i) {
return new Option(stock.name, i)
}))
})
function format(data, multiplier, digits) {
data = data.slice()
data[0] = (+(data[0] * multiplier).toFixed(digits)).toLocaleString()
return data.join(' ')
}
function stockFacts(stock, quantity) {
return [
format(stock.calories, quantity, 2) + ' calories<br>' +
format(stock.protein, quantity, 2) + ' of protein<br>' +
format(stock.fat, quantity, 3) + ' of fat<br>' +
format(stock.saturatedFat, quantity, 2) + ' of saturated fat<br>' +
format(stock.sugar, quantity, 2) + ' of sugar<br>' +
format(stock.sodium, quantity, 2) + ' of sodium<br>' +
format(stock.cholesterol, quantity, 2) + ' of cholesterol<br>'
]
}
$selects.add($quantity).on('input', updateAmount)
function getStock (select) {
return stocks[+select.value]
}
function updateAmount() {
var quantity = +$quantity.val() 

$selects.each(function() {
var $result = $(this).nextAll('.result').empty()
var $amount = $(this).prev().find('.servingUnit').empty()
var stock = getStock(this)
if (!stock) return
var amount = quantity * stock.unitsPerServing

$amount.text(' (' + amount + ' ' + stock.servingUnit + ')')

$result.html(stockFacts(stock, amount))
})

var selected = [].map.call($selects, getStock)
$comparisonResult.empty()
if (!selected[0] || !selected[1]) return
var diff = {}
Object.keys(selected[0]).forEach(function (k) {
if (/^(name|servingUnit|unitsPerServing)$/.test(k)) return
var first = selected[0][k].slice()
var second = selected[1][k].slice()
first[0] *= selected[0].unitsPerServing
second[0] *= selected[1].unitsPerServing
diff[k] = [Math.abs(first[0] - second[0]), first[1], first[0] > second[0] ? 'more' : 'less']
})
$comparisonResult.html(stockFacts(diff, quantity))
}
.side,
.comparison {
width: 33.333%;
display: inline-block;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<meta name="viewport" content="width=10px, initial-scale=1.0">
</head>
<body>
<label>
Servings:
<input type="number" id="numberOfStocks" value="1" min="0" />
</label>
<div>
<div class="side">
<h2>First Item<span class="servingUnit"></span>:</h2>
<select class="selectStock">
<option value="-1">Pick a food!</option>
</select>
<br>
<br>
<div class="result"></div>
</div>
<div class="side">
<h2>Second Item<span class="servingUnit"></span>:</h2>
<select class="selectStock">
<option value="-1">Pick a food!</option>
</select>
<br>
<br>
<div class="result"></div>
</div>
<div class="comparison">
<h2>Comparison:</h2>
<br>
<br>
<div class="result"></div>
</div>
</div>
</body>

我在 JS 小提琴上制作了您的问题的简化版本,如果这里的格式/链接错误,mod 可以更正:

[1]: https://jsfiddle.net/xnymo46d/17/JS 小提琴代码

// Create food objects to hold info about the food
var food = [];
food[0] = { name: "Beef", calories:"70", protein:"25" }
food[1] = { name: "Chicken", calories:"80", protein:"30" }
food[2] = { name: "Steak", calories:"150", protein:"20" }
// Store food in dropdowns on load
for (i = 0; i < food.length; ++i) 
$("select[name='food[]']").append('<option value="' + i + '">' + food[i].name + '</option>');
// Call a function to calculate differences when options are changed
$('select').on('change', function() {
getDifference();
})
function getDifference()
{
// Get the selected food options
var foodOptions = $("select[name='food[]']").map(function(){return $(this).val();}).get();
var calories = [];
var protein = [];
for (i = 0; i < foodOptions.length; ++i)
{
var thisIndex = $("select[name='food[]']").eq(i).val();
calories[i] = food[thisIndex].calories;
protein[i] = food[thisIndex].protein;
}
// calculate difference between calories
var differenceCalories = calories[0] - calories[1];
var differenceProtein = protein[0] - protein[1];
if (!differenceCalories)
$("#result-calories").html('The calories are the same between your selected food items');
else if (differenceCalories > 0)
$("#result-calories").html('There are ' + differenceCalories + ' more calories in your first selection than second');
else
$("#result-calories").html('There are ' + (differenceCalories * -1) + ' less calories in your second selection than first');
if (!differenceProtein)
$("#result-protein").html('The protein is the same between your selected food items');
else if (differenceProtein > 0)
$("#result-protein").html('There are ' + differenceProtein + ' more grams of protein in your first selection than second');
else
$("#result-protein").html('There are ' + (differenceProtein * -1) + ' less grams of protein in your second selection than first');
}

我认为如果您将食物项目制作成类似于我所做的 JS对象,您的代码会更容易解释/使用。这样,您可以为每个食物提供标识符(例如卡路里、蛋白质等)。因为现在,您对股票(食物)的代码非常混乱;你有所有这些数字,但不知道它们代表什么(我假设其他因素,包括脂肪、钠、碳水化合物等)。也许你会,但我没有,即使为了你,它看起来很难/令人困惑。创建对象数组后,我遍历所有对象并将 t hem 附加到下拉列表中,类似于您的方式。 然后,我创建了一个函数,在下拉列表更改时遍历所有下拉选择,加载其所选值并收集所选的食物项。(你甚至可以把它绑在一个按钮或其他东西上)。然后,我将卡路里和蛋白质存储在不同的阵列中,并比较了两者。此步骤可以按照您想要的任何方式完成;您甚至可以收集两种食物对象。

有很多不同的方法可以解决这个问题。这对我来说是粗略的;您有一种更有效/优化的方式来存储有关食物(库存)的数据,并且您有一种无需编写冗余代码即可动态加载下拉列表的方法。我也这样做的方式,你也可以使用无限数量的下拉菜单(比如如果你想比较 4、6 甚至 100 种不同的食物)。当然,您必须修改计算差异的方式。无论如何,希望这有助于引导您朝着正确的方向前进。

最新更新