2017-04-13 31 views
0

我有一個食物項目營養成分數組的數據庫。我所要做的就是選擇2個項目的結果是第一個項目和第二個項目的值之間的差異。例如,如果第一個項目是72卡路里,而另一個項目是50卡路里,我希望輸出說「22多卡路里,x更多克蛋白質,y更多克脂肪,等等。如果項目逆轉,我希望它說22卡路里,等等。從下拉菜單(Javascript)輸出兩個數組值的差異

這是我到目前爲止的代碼。我能夠輸出每個項目的值,但還沒有想出如何輸出的差異:

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>

會在此欣賞指導。謝謝一堆!

回答

1

我玩了一段代碼,並設法想出了一個解決方案。我添加的邏輯有些複雜,所以如果您有任何問題,請告訴我。我稍後可能會回來修改我寫的代碼,使其更清晰一些。我盡我所能不要改變你原來的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>

+0

這是awesome-感謝一大堆!我基本上從CSV導入這個,所以我可以轉換成JSON對象,如果更容易。股票[17]應該是服務量(例如4意味着4盎司),我需要它是文本框中的自動價值。你知道我怎麼能做到這一點?另一件事是,我需要有服務單位(例如盎司)以數量(盎司)顯示,以便它是動態的,如果單位是克,液體盎司,升等。你知道我會怎麼樣能夠做到這一點呢?謝謝一堆 –

+0

是的,我應該可以做到這一點。我目前無法編輯我的答案,但給我一兩個小時,我會盡快回復您。 – gyre

+0

我還是不明白'股票[17]'應該得到多少。 。 。你能給我完整的CSV嗎?我做了一些清理代碼並添加了動態單元;讓我知道這是否符合你的希望。我會稍後再清理它,當我找到時間:) – gyre

1

我在這裏提出您的問題的一個簡化版本上JS小提琴,如果格式化/鏈接是錯在這裏國防部可以糾正:

[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 對象與我所做的相似,那麼認爲你的代碼會更容易解釋/處理。這樣,您可以爲每個食物提供標識符(例如卡路里,蛋白質等)。因爲現在,你對股票(食品)的代碼非常混亂;你有這些數字,不知道他們代表什麼(我假設其他因素,包括脂肪,鈉,碳水化合物等)。也許你會這樣做,但是我不這樣做,即使爲了你的緣故,看起來很難/令人困惑。在創建一個對象數組後,我循環遍歷所有這些對象並將其拖放到下拉菜單中,與您的操作方式類似。 然後我做了一個功能,當下拉改變時加載所有下拉選項,加載它們的選定值並收集所選的食物項目。 (你甚至可以把它綁到一個按鈕或其他東西)。然後我將卡路里和蛋白質儲存在不同的陣列中,並將兩者進行比較。這一步可以以任何你想要的方式完成;你甚至可以收集兩個食物。

有很多不同的方法可以解決這個問題。這樣做很粗糙,我會這樣做;您有更高效/最優化的方式來存儲有關食品(庫存)的數據,並且您可以通過下拉菜單動態加載而無需編寫冗餘代碼。我也是這樣做的,你可以使用無限量的下拉菜單(例如,如果你想比較4,6甚至100種不同的食物)。當然,你將不得不修改你計算差異的方式。無論如何,希望能夠幫助你指引正確的方向。