在Javascript中重新创建查找表

时间:2016-04-19 12:26:10

标签: javascript arrays

所以我有一个用于检索会员费率的电子表格,列是Age,Duration&率。您只需查看年龄列以查找客户的年龄,然后当您发现该年龄时,您将继续向下以使其与正确的持续时间相匹配,那么在最后一列中将是费率。 (非常)小版本可能看起来像这样;

Age,Duration,Rate
18,10,1.33
18,11,1.5
18,12,1.8
19,10,1.4
19,11,1.65
19,12,1.88
20,10,1.48
20,11,1.73
20,12,1.98

所以19岁的人,持续时间11的比率是1.65。年龄在20岁,持续时间为12岁的人的比率为1.98 - 很容易!

我的问题是两个部分,我想将其转换为一个网页,其中有人输入年龄和持续时间来检索费率。我非常确定我最好的选择是像这样的二维数组;

var array = [[18,10,1.33],[18,11,1.5],[18,12,1.8] .. and so on];

还有更好的选择吗?

第二个问题是如何最好地迭代二维数组(如果这最终成为最佳解决方案)?正如我之前提到的,我需要能够进行基于两个标准搜索的返回率的迭代。我相信这将包括一个两部分的迭代,但迭代对我来说是一个弱点,试图掌握在循环中的位置,我的迭代只是大脑融化。我认为它看起来像是这样;

for (var i = 0; i < array.length; i++){
for (var j = 0; j < array[i].length; j++){
    //Do something... I think something like this
    If array[][j] == ageImLookingFor && array[][j+1] == durationImLookingFor
    then return array[][j+2] (which is the rate)
  }
}

任何帮助,建议或想法我都会非常感激

4 个答案:

答案 0 :(得分:2)

比使用数组更好的选择是使用对象(或Map),其属性(键)对应于年龄和持续时间的有效组合,通过该键有效地索引数据:

var list = {
     '18_10': { age: 18, duration: 10, rate: 1.33 }
     '18_11': { age: 18, duration: 11, rate: 1.5 },
     '18_12': { age: 18, duration: 11, rate: 1.8 },
     // .. and so on
};

这样你就不必遍历一个数组(参见你的问题#2),但考虑到年龄和持续时间(假设在具有这些名称的变量中),你可以写这个来获得匹配的项目:

var item = list[age + '_' + duration];

当然,您应该检查年龄持续时间是否为有效整数,并且可以是undefined时这个组合是未知的。

这是一个简单的代码段(没有任何检查),您可以使用它来构建您的Web表单。它从具有数据的数组构建上述对象。

// Data in array -- will be keyed later
var arr = [
    { age: 18, duration: 10, rate: 1.33 },
    { age: 18, duration: 11, rate: 1.5 },
    { age: 18, duration: 12, rate: 1.8 },
    { age: 19, duration: 10, rate: 1.4 },
    { age: 19, duration: 11, rate: 1.65 },
    { age: 19, duration: 12, rate: 1.33 },
    { age: 20, duration: 10, rate: 1.48 },
    { age: 20, duration: 11, rate: 1.73 },
    { age: 20, duration: 12, rate: 1.98 },
];

// Build map, keyed by age/duration. It will look like:
//   { 
//      '18_10': { age: 18, duration: 10, rate: 1.33 },
//      '18_11': { age: 18, duration: 11, rate: 1.33 },
//       ...etc
//   }
mapByAgeDuration = {};
for (var i=0; i < arr.length; i++) {
    mapByAgeDuration[arr[i].age + '_' + arr[i].duration] = arr[i];
}

// Fast retrieval function:
function getItemFor(age, duration) {
    return mapByAgeDuration[age + '_' + duration];
}

// I/O

var button = document.getElementById('findRate');
var inputAge = document.getElementById('age');
var inputDuration = document.getElementById('duration');
var outputRate = document.getElementById('rate');

button.onclick = function() {
    var age = inputAge.value;
    var duration = inputDuration.value;
    
    // Retrieve item for this age and duration
    var item = getItemFor(age, duration);

    // Output rate
    outputRate.textContent = item !== undefined ? item.rate 
                             : 'not a valid combination';
}
Age (18 - 20): <input id="age"><br>
Duration (10 - 12): <input id="duration"><br>
<button id="findRate">Find Rate</button><br>
Rate: <span id="rate"></span><br>

答案 1 :(得分:1)

Q1:您可以使用哈希表进行查找。

&#13;
&#13;
var data = [[18, 10, 1.33], [18, 11, 1.5], [18, 12, 1.8], [19, 10, 1.4], [19, 11, 1.65], [19, 12, 1.88], [20, 10, 1.48], [20, 11, 1.73], [20, 12, 1.98]],
    object = {};

data.forEach(function (a) {
    object[a[0]] = object[a[0]] || {};
    object[a[0]][a[1]] = a[2];

});

// usage
document.write(object[19][11] + '<br>');
document.write(object[20][12] + '<br>');

document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
&#13;
&#13;
&#13;

Q2:Array#some()

的提案

如果您已对数据进行排序,则可以插入短路,如果值大于此值。

&#13;
&#13;
var data = [[18, 10, 1.33], [18, 11, 1.5], [18, 12, 1.8], [19, 10, 1.4], [19, 11, 1.65], [19, 12, 1.88], [20, 10, 1.48], [20, 11, 1.73], [20, 12, 1.98]],
    object = {};

function getValue(p1, p2) {
    var result;
    data.forEach(function (a) {
        if (a[0] === p1 && a[1] === p2) {
            result = a[2];
            return true;
        }
        // short circuit for not found values
        return a[0] > p1;           
    });
    return result;
}

// usage
document.write(getValue(19, 11) + '<br>');
document.write(getValue(20, 12) + '<br>');
&#13;
&#13;
&#13;

答案 2 :(得分:1)

另一种方法是利用array.filter函数。 您必须将数据重塑为对象数组:

var rates = [
	{'age':'18','duration':'10','rate':'1.33'},
	{'age':'18','duration':'11','rate':'1.5'},
	{'age':'19','duration':'12','rate':'1.8'}
];

function filterRate(item){
	if(item.age == this.age && item.duration == this.duration)
		return item;
}

function getRateByAgeDuration(age, duration){
	res = null;
	try{
		res = rates.filter(filterRate, {'age':age, 'duration':duration})[0].rate;
	}
	catch(ex){ console.log(ex);}
	return res;
}

document.write(getRateByAgeDuration('18', '10'));

答案 3 :(得分:1)

这取决于。如果使用哈希值,平均时间为O(1),但最坏情况下为O(n)。

如果您希望优化最坏情况,可以使用二分搜索在平均和最差情况下实现O(lg n)。

function binarySearch(array, data, from=0, to=array.length) {
  if(from >= to) return -1; // not found
  var m = Math.floor((from+to)/2);
  for(var i=0; i<data.length; ++i) {
    if(data[i] < array[m][i]) return binarySearch(array, data, from, m);
    if(data[i] > array[m][i]) return binarySearch(array, data, m+1, to);
  }
  return m;
}
var idx = binarySearch(array, [18,12]);
if(idx > -1) array[idx];