Функция bisectLeft не работает, если второй параметр является числовым

#javascript #d3.js

#javascript #d3.js

Вопрос:

В небольшой процедуре, которую я реализую, я использую функцию bisectLeft из d3.js. Я использую последнюю версию (v5.9.2). Если я это сделаю, все будет в порядке:

 var dataArray = [10, 20, 50, 40, 30, 600];
d3.bisectLeft(dataArray, 30); //2
  

Но если я сделаю это, нет:

 var dataArray = [[10,1],[20,2],[50,5],[40,4],[30,3],[600,60]];
d3.bisectLeft(dataArray, 30); //0 Bad!
  

Это, однако, работает хорошо:

 var dataArray = [[10,1],[20,2],[50,5],[40,4],[30,3],[600,60]];
d3.bisectLeft(dataArray, '30'); //2 Good!
  

Это так задумано? Я просмотрел исходный код и документацию и не понимаю, почему это происходит.
После того, как я узнал, что проблему очень легко исправить в моем коде, но у меня все еще есть сомнения, и я не знаю, не упускаю ли я чего-то.

Ответ №1:

Проблема здесь в том, что у вас есть массив массивов. В этом случае вам придется использовать d3.bisector с соответствующей функцией доступа, чтобы D3 мог знать, какое значение сравнивать. Согласно документам, этот метод…

Возвращает новую биссектрису с использованием указанного средства доступа или функции сравнения. Этот метод можно использовать для разделения пополам массивов объектов вместо того, чтобы ограничиваться простыми массивами примитивов. (выделено мной)

В вашем случае это будет:

 const bisector = d3.bisector(function(d) { return d[0]; }).left;
  

Как вы можете видеть, это эффективно превратит массив массивов в единый массив чисел, выбрав первое число в каждом внутреннем массиве, точно так же, как первый фрагмент в вашем вопросе.

Также обратите внимание на тот факт, что массив необходимо отсортировать (иначе люди никогда не поймут, почему в вашем вопросе 2 это «хорошо»!).

Это демонстрационный:

 var dataArray = [
  [10, 1],
  [20, 2],
  [50, 5],
  [40, 4],
  [30, 3],
  [600, 60]
];
dataArray = dataArray.sort(function(a, b) {
  return a[0] - b[0];
});
const bisector = d3.bisector(function(d) {
  return d[0];
}).left;
const result = bisector(dataArray, 30);

console.log(result)  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>  

Комментарии:

1. Опереди меня, хороший ответ. Необходимо предупреждение о том, что вы вводите ответ, чтобы сэкономить время.

2. @AndrewReid Остается загадкой: почему и как строка работала для биссектрисы? Возможно, вы захотите изучить это и опубликовать в качестве ответа.

3. Это исправляет проблему. Спасибо!