在数组范围中查找索引

时间:2015-06-29 15:17:59

标签: javascript jquery arrays sorting

我有一个数量数组,我想找到这个数组中找到数字的位置。因此,如果用户输入16,则该函数将在索引6和6之间返回。因为16大于15但小于20。

在更广泛的图片中,该索引将用于查找以查找所需数量的价格区间。

修改

HTML标记

<table cellpadding="0" cellspacing="0" border="0">
    <tbody><tr>
        <th scope="row">Quantity</th>
        <th id="js-QuantityID-0" scope="col">0</th>
        <th id="js-QuantityID-1" scope="col">1</th>
        <th id="js-QuantityID-2" scope="col">2</th>
        <th id="js-QuantityID-3" scope="col">3</th>
        <th id="js-QuantityID-4" scope="col">4</th>
        <th id="js-QuantityID-5" scope="col">5</th>
        <th id="js-QuantityID-6" scope="col">10</th>
        <th id="js-QuantityID-7" scope="col">15</th>
        <th id="js-QuantityID-8" scope="col">20</th>
        <th id="js-QuantityID-9" scope="col">30</th>
        <th id="js-QuantityID-10" scope="col">40</th>
        <th id="js-QuantityID-11" scope="col">50</th>
        <th id="js-QuantityID-12" scope="col">60</th>
    </tr>
    <tr>
        <th scope="row">Price (inc. VAT)</th>
        <td id="js-PriceID-0">0.00</td>
        <td id="js-PriceID-1">45.60</td>
        <td id="js-PriceID-2">38.40</td>
        <td id="js-PriceID-3">32.40</td>
        <td id="js-PriceID-4">34.56</td>
        <td id="js-PriceID-5">30.72</td>
        <td id="js-PriceID-6">26.80</td>
        <td id="js-PriceID-7">21.60</td>
        <td id="js-PriceID-8">20.60</td>
        <td id="js-PriceID-9">17.60</td>
        <td id="js-PriceID-10">16.60</td>
        <td id="js-PriceID-11">15.60</td>
        <td id="js-PriceID-12">14.00</td>
    </tr>
    </tbody>
</table>

工作脚本

function getTableContents() {
    var productArray = [];

    jQuery("th[id^='js-QuantityID-']").each(function () {
        var n = jQuery(this).attr("id").replace('js-QuantityID-', ''); // get the number from the id

        productArray.push({
            qty: parseInt(jQuery(this).text()),
            price: parseFloat(jQuery('#js-PriceID-' + n).text().replace('£',''))
        });
    });

    return productArray = cleanArray(productArray);
}

答案

问题是由于将Quantity作为一个字符串,在解析为整数时解决了我的问题@Michael Geary

6 个答案:

答案 0 :(得分:3)

在您的示例中,设置具有匹配元素(如pricequantity数组的并行数组通常不是一个好主意。这很容易出错,很难在视觉上匹配哪个价格与哪个数量相符。

相反,您应该使用单个数组,其中每个数组元素都是一个结合数量级别和价格的对象:

var priceBands = [
    { qty:  1, price: '£45.60' },
    { qty:  2, price: '£38.40' },
    { qty:  3, price: '£32.40' },
    { qty:  4, price: '£32.10' },
    { qty:  5, price: '£34.56' },
    { qty: 10, price: '£30.72' },
    { qty: 15, price: '£26.80' },
    { qty: 20, price: '£21.60' },
    { qty: 30, price: '£21.00' },
    { qty: 40, price: '£21.00' }
];

现在很容易看出哪个价格与哪个数量有关,并且在两个数组中都没有相同数量的元素。

(顺便说一下,我好奇为什么价格在5个项目上 up !)

如果这种符号看起来太单调乏味,你可以轻松地简化它:

var priceBands = makePriceBands([
    ' 1: £45.60',
    ' 2: £38.40',
    ' 3: £32.40',
    ' 4: £32.10',
    ' 5: £34.56',
    '10: £30.72',
    '15: £26.80',
    '20: £21.60',
    '30: £21.00',
    '40: £21.00',
]);

它产生前面列出的相同对象数组,使用此函数转换更简洁的表示法:

function makePriceBands( bandsIn ) {
    var bands = [];
    for( var i = 0;  i < bandsIn.length;  ++i ) {
        var band = bandsIn[i].split(/: */));
        bands.push({ qty: +band[0], price: band[1] });
    }
    return bands;
}

对于现代浏览器,您可以更简单地写一下:

function makePriceBands( bands ) {
    return bands.map( function( b ) {
        var band = b.split(/: */));
        return { qty: +band[0], price: band[1] };
    });
}

但第一个版本适用于任何旧浏览器。

无论哪种方式,找到合适价格的代码都很简单。向后走过数组,直到到达输入数量大于或等于数组元素数量的元素。

我们将这个函数设为一个prices数组作为参数,因此您可以通过传入不同的数组将它用于不同的产品。

另外,当你的输入数量等于到一个价格水平数量时,你没有在你的问题中指明该做什么,所以我做了一个假设,例如,如果你有10个或更多,你得到数量10的价格水平。(换句话说,你不必购买11来获得数量10的价格。)

function priceForQuantity( prices, n ) {
    for( var i = prices.length - 1;  i >= 0;  --i ) {
        if( n >= prices[i].qty ) {
            return prices[i].price;
        }
    }
    return '£0.00';
}

或者你可以向前走过阵列,但我发现通过向后走来更容易思考这个特殊问题。

您可以使用一些示例数量测试此代码,确保测试比特定数量级别更大和更小的边界条件:

function test( n ) {
    console.log( n, priceForQuantity( priceBands, n ) );
}

test( 0 );
test( 1 );
test( 3 );
test( 5 );
test( 6 );
test( 9 );
test( 10 );
test( 39 );
test( 40 );
test( 41 );

这将记录:

0 "£0.00"
1 "£45.60"
3 "£32.40"
5 "£34.56"
6 "£34.56"
9 "£34.56"
10 "£30.72"
39 "£21.00"
40 "£21.00"
41 "£21.00"

答案 1 :(得分:2)

感谢您提供有关您的用例与定价范围的其他详细信息。我觉得这些方面的东西应该适合你想要做的事情;注意数量数组的变化 - 我改变了#34; 40 +&#34;到41,但只要您对qtysprices具有相同的数组长度,您只需输入一次最高数量/最低价格...超过该阈值的任何数量都将获得正确的数量找到数量数组结束时的价格。 http://jsfiddle.net/4oyrd0d2/

var qtyOrdered = 45; // From order/bid input

var qtys =   [1,2,3,4,5,10,15,20,30,40,41]; // Quantity Array
var prices = ["£45.60", "£38.40", "£32.40", "£32.10", "£34.56", "£30.72", "£26.8", "£21.6", "£21.0", "£21.0", "£20.0"]; // Price Bands

var qtyIdx = 0, qtyBand, priceIdx;
do {
    priceIdx = qtyIdx; // assigns the current price, only changed -after- each 'while' condition passes
    qtyBand = qtys[++qtyIdx];
}
while(qtyBand <= qtyOrdered && priceIdx < qtys.length);

var effectivePrice = prices[priceIdx];

答案 2 :(得分:0)

var value = 16,
    index = ary.indexOf(ary.filter(function (item, index) {
        var first = item,
            second = ary[index + 1] || false;
        return value >= first && (!second || value <= second);
    })),
    range = 'between index ' + index + ' and ' + (index + 1);

答案 3 :(得分:0)

如果您的数组已排序,则可以使用dichotomic search

function dicSearch(arr, item, from=0, to=arr.length) {
  if(from === to) return [to-1, to];
  var mid = Math.floor((from + to) / 2);
  if(arr[mid] > item) return dicSearch(arr, item, from, mid);
  if(arr[mid] < item) return dicSearch(arr, item, mid+1, to);
  return [mid, mid];
}
var arr = [1, 2, 3, 4, 5, 10, 15, 20, 30, 40];
dicSearch(arr, 0);  // [-1,0]
dicSearch(arr, 15); // [6,6]
dicSearch(arr, 16); // [6,7]
dicSearch(arr, 50); // [9,10]

答案 4 :(得分:0)

我认为这比过滤器更容易掌握

&#13;
&#13;
var q = [1,2,3,4,5,10,15,20,30,40],
price = [45.60,38.40,32.40,32.10,34.56,30.72,26.8,21.6,21.0,21.0];
function getPrice(num) {
  for (var i = q.length-1;i>=0;i--) {
    if (num >= q[i]) {
      return q[i]+" @ £"+price[i].toFixed(2)+": £"+(num*price[i]).toFixed(2);
    }
  } 
  return "Not understandable quantity";
}
alert(getPrice(26));
&#13;
&#13;
&#13;

答案 5 :(得分:0)

尝试此搜索,这也应该有用。 在这里,如果输入的数字与任何数组元素相同。如果你想要的话,你可以选择更高的值。

var t=["1", "2", "3", "4", "5", "10", "15", "20", "30", "40"];

var y=prompt("Enter a value:");
var i=0;
$.each(t,function(u,v){
    console.log(u);
   if(parseFloat(y)<parseFloat(v) && parseFloat(y)>parseFloat(t[u-1]))
   {
       i=u-1;
   } 
   if(parseFloat(y)==parseFloat(v))
   {
       i=u-1;
   }
});
alert("Element between index "+(i)+ " and "+ (i+1));

小提琴:http://jsfiddle.net/ktozktch/25/