在javascript中实现类似函数的vlookup

时间:2017-12-07 21:09:11

标签: javascript reactjs sorting

我的React组件状态中有一个对象,如下所示:

const elementPositions =  {
  "0": 180.2,
  "1": 350.8666666666667,
  "2": 521.5333333333333,
  "3": 692.2,
  "4": 862.8666666666667,
  "5": 1033.5333333333333,
  "6": 1204.2
}

我有滚动侦听器,它返回一个滚动位置值,让我们在这个例子中说const scrollY = 466

我需要创建一个返回滚动位置的相应索引的函数 - 即466将返回1,因为它大于350但小于521。实现这一目标的最佳方法是什么?我正在思考这方面的事情,但我不确定它是最好的方法:

const values = Object.values(elementPositions)
values.push(scrollY)
values.sort((a, b) => {return a-b})
const newIndex = values.indexOf(scrollY) - 1 

2 个答案:

答案 0 :(得分:2)

假设elementPositions是一个数组:

[180.2, 350.866, ...]

这将返回O(n)中的值(优于排序):

// Get all values smaller than current scrollY
positions = elementPositions.filter(e => e <= scrollY);

// The last element will be the one closest
value = positions.length ? positions[positions.length - 1] : elementPositions[0];

然后,您可以根据需要使用.indexOf获取索引。

这绝不是有效的,你不应该在每个滚动事件上都这样做。

最有效的方法可能是进行O(log n)的二进制搜索:

&#13;
&#13;
function rec_search(array, value, left, right) {
    if (right - left == 1) return left;
    var middle = Math.floor((left + right) / 2),
        middleValue = array[middle];
    if (value < middleValue) return rec_search(array, value, left, middle);
    else return rec_search(array, value, middle, right);
}

function search(array, value) {
    if (array.length == 0) return -1;
    if (value < array[0]) return -1;
    if (value > array[array.length - 1]) return array.length - 1;
    return rec_search(array, value, 0, array.length - 1);
}

var positions = [1, 2, 4, 8, 16, 32];  // sorted array
console.log(search(positions, 7));
&#13;
&#13;
&#13;

如果您知道生成数字的函数,也可以用代数方式计算索引。

答案 1 :(得分:2)

你的数字似乎是大约170的增量,所以你应该能够在恒定时间内进行算术运算(没有排序,循环等)。

&#13;
&#13;
const elementPositions =  {
  "0": 180.2,
  "1": 350.8666666666667,
  "2": 521.5333333333333,
  "3": 692.2,
  "4": 862.8666666666667,
  "5": 1033.5333333333333,
  "6": 1204.2
};

function getPos(x) {
  return elementPositions[Math.floor((x-180.2) / 170.66666666666)] || 0;
}

// test
for (const n of [0,10,180,181,350,351,466,521,522,692,693,862,863,1033,1034,1204,1205]) {
  console.log(n, getPos(n));
}
&#13;
&#13;
&#13;