#javascript #arrays #d3.js
#javascript #массивы #d3.js
Вопрос:
У меня есть программа D3, которая строит линейную диаграмму, где есть две линии, и я хочу определить координаты в месте пересечения линий. Есть ли у D3 функция для этого? Массивы часто имеют разную длину и генерируются динамически, но всегда будут иметь одно значение, при котором оба будут равны по одному и тому же индексу.
например
var line1 = [0,1,2,3,4];
var line2 = [4,3,2,1,0];
В данном случае ответ = индекс 2. Если для этого нет функции D3, какой был бы наилучший подход с использованием ES6 и выше?
Ответ №1:
В D3 есть совершенно неизвестный метод named d3.zip
, который мы можем использовать для объединения массивов и поиска любого внутреннего массива, в котором все элементы равны:
var line1 = [0, 1, 2, 3, 4];
var line2 = [4, 3, 2, 1, 0];
var zip = d3.zip(line1, line2).reduce(function(a, c, i) {
if (c[0] === c[1]) a.push(i);
return a;
}, []);
console.log(zip)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Приятно то, d3.zip
что он может использоваться с несколькими массивами, а также сохраняет длину более короткого массива. Итак, в более сложном случае (равные значения в индексах 6 и 9):
var line1 = [0, 1, 2, 3, 9, 9, 1, 4, 7, 6, 5, 4];
var line2 = [4, 3, 2, 1, 0, 8, 1, 2, 3, 6, 1];
var line3 = [9, 9, 9, 9, 4, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1];
var zip = d3.zip(line1, line2, line3).reduce(function(a, c, i) {
const every = c.every(function(e) {
return e === c[0]
})
if (every) a.push(i);
return a;
}, []);
console.log(zip)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Ответ №2:
const [longer, shorter] = line1.length > line2.length ? [line1, line2] : [line2, line1];
const crossIndex = shorter.reduce((crossIndex, value, index) => {
if (crossIndex !== null) {
// already found it! just return
return crossIndex;
}
// find it! return
if (value === longer[index]) return index;
// no found, continue searching
return crossIndex;
}, null)
Если вы не возражаете, что поиск требует нескольких дополнительных бесполезных итераций, первый шаг, на котором мы выясняем, какая строка длиннее или короче, на самом деле не нужен. Вы вызываете .reduce()
либо строку 1, либо строку 2, затем снова сравниваете другую, вы все равно получите тот же результат.