Spec-Zone.ru › D3.js 3

Массивы

Ссылка на API ▸ Основные элементы ▸ Массивы

При работе с D3 — и в целом при визуализации данных — часто приходится проводить множество операций с массивами. Это связано с тем, что каноническое представление данных в D3 — это массив. Некоторые распространённые операции с массивами включают извлечение непрерывного среза (подмножества) массива, фильтрацию массива с помощью предикатной функции и отображение массива на параллельный набор значений с помощью функции преобразования. Перед изучением утилит для работы с массивами, предоставляемых D3, вы должны ознакомиться с мощными методами массивов, встроенными в JavaScript.

JavaScript включает в себя методы-мутаторы, которые изменяют массив:

  • array.pop - Удаляет последний элемент из массива.
  • array.push - Добавляет один или несколько элементов в конец массива.
  • array.reverse - Изменяет порядок элементов в массиве на обратный.
  • array.shift - Удаляет первый элемент из массива.
  • array.sort - Сортирует элементы массива.
  • array.splice - Добавляет или удаляет элементы из массива.
  • array.unshift - Добавляет один или несколько элементов в начало массива.

Также существуют методы-аксессоры, которые возвращают некоторое представление массива:

  • array.concat - Объединяет массив с другими массивами или значениями.
  • array.join - Объединяет все элементы массива в строку.
  • array.slice - Извлекает часть массива.
  • array.indexOf - Находит первое вхождение значения в массиве.
  • array.lastIndexOf - Находит последнее вхождение значения в массиве.

И, наконец, методы итерации, применяющие функции к элементам массива:

  • array.filter - Создаёт новый массив, содержащий только те элементы, для которых предикат истиннен.
  • array.forEach - Вызывает функцию для каждого элемента массива.
  • array.every - Проверяет, удовлетворяет ли каждый элемент массива предикату.
  • array.map - Создаёт новый массив, содержащий результаты вызова функции для каждого элемента массива.
  • array.some - Проверяет, удовлетворяет ли хотя бы один элемент массива предикату.
  • array.reduce - Применяет функцию к массиву для сведения его к одному значению (слева направо).
  • array.reduceRight - Применяет функцию к массиву для сведения его к одному значению (справа налево).

Сортировка

d3.ascending(a, b)

Возвращает -1, если a меньше b, или 1, если a больше b, или 0. Это функция компаратора для естественного порядка и может использоваться совместно со встроенным методом сортировки массивов для упорядочения элементов в порядке возрастания. Реализуется как:

function ascending(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

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

d3.descending(a, b)

Возвращает -1, если a больше b, или 1, если a меньше b, или 0. Это функция компаратора для обратного естественного порядка и может использоваться совместно со встроенным методом сортировки массивов для упорядочения элементов в порядке убывания. Реализуется как:

function descending(a, b) {
  return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

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

d3.min(array[, accessor])

Возвращает минимальное значение в заданном array с использованием естественного порядка. Если массив пуст, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением минимального значения. В отличие от встроенной Math.min, этот метод игнорирует неопределённые значения; это полезно для вычисления области масштаба, учитывая только определённую область данных. Кроме того, элементы сравниваются с использованием естественного порядка, а не числового.

d3.max(array[, accessor])

Возвращает максимальное значение в заданном array с использованием естественного порядка. Если массив пуст, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением максимального значения. В отличие от встроенной Math.max, этот метод игнорирует неопределённые значения; это полезно для вычисления области масштаба, учитывая только определённую область данных. Кроме того, элементы сравниваются с использованием естественного порядка, а не числового.

d3.extent(array[, accessor])

Возвращает минимальное и максимальное значения в заданном array с использованием естественного порядка. Это эквивалентно одновременным вызовам d3.min и d3.max.

d3.sum(array[, accessor])

Возвращает сумму элементов в заданном array. Если массив пуст, возвращает 0. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением суммы. Этот метод игнорирует недопустимые значения, такие как NaN и undefined; это полезно для вычисления суммы данных, учитывая только хорошо определённые значения.

d3.mean(array[, accessor])

Возвращает среднее значение в заданном array. Если массив пуст, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением среднего значения. Этот метод игнорирует недопустимые значения, такие как NaN и undefined; это полезно для вычисления среднего значения данных, учитывая только хорошо определённые значения.

d3.median(array[, accessor])

Возвращает медиану заданного array, используя алгоритм R-7. Если массив пуст, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением медианы. Этот метод игнорирует недопустимые значения, такие как NaN и undefined; это полезно для вычисления медианы данных, учитывая только хорошо определённые значения.

d3.quantile(numbers, p)

Возвращает p-квантиль заданного отсортированного массива numbers, где p — число в диапазоне [0, 1]. Например, медиана может быть вычислена с использованием p = 0,5, первый квартиль — при p = 0,25, а третий квартиль — при p = 0,75. Данная реализация использует алгоритм R-7, который является стандартным в языке программирования R и Excel. Для данного метода требуется, чтобы numbers содержал числовые элементы и уже был отсортирован в порядке возрастания, например, с помощью d3.ascending.

var a = [0, 1, 3];
d3.quantile(a, 0); // 0
d3.quantile(a, 0.5); // 1
d3.quantile(a, 1); // 3
d3.quantile(a, 0.25); // 0.5
d3.quantile(a, 0.75); // 2
d3.quantile(a, 0.1); // 0.19999999999999996
d3.variance(array[, accessor])

Возвращает несмещённую оценку дисперсии заданного array чисел. Если массив содержит меньше двух значений, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением дисперсии. Этот метод игнорирует недопустимые значения, такие как NaN и undefined.

d3.deviation(array[, accessor])

Возвращает стандартное отклонение, определяемое как квадратный корень из несмещённой оценки дисперсии, заданного array чисел. Если массив содержит меньше двух значений, возвращает undefined. Можно указать необязательную функцию accessor, которая эквивалентна вызову array.map(accessor) перед вычислением стандартного отклонения. Этот метод игнорирует недопустимые значения, такие как NaN и undefined.

d3.bisectLeft(array, x[, lo[, hi]])

Найдите точку вставки для x в массиве, чтобы сохранить сортированный порядок. Аргументы lo и hi можно использовать для указания подмножества массива, которое следует учитывать; по умолчанию используется весь массив. Если x уже присутствует в массиве, точка вставки будет находиться перед (слева от) любыми существующими записями. Значение возврата подходит для использования в качестве первого аргумента splice, предполагая, что массив уже отсортирован. Возвращенная точка вставки i разбивает массив на две половины таким образом, что все v < x для v в массиве.slice(lo, i) для левой стороны и все v >= x для v в массиве.slice(i, hi) для правой стороны.

d3.bisect(массив, x[, lo[, hi]])
d3.bisectRight(массив, x[, lo[, hi]])

Аналогично bisectLeft, но возвращает точку вставки, которая находится после (справа от) любых существующих записей x в массиве. Возвращенная точка вставки i разбивает массив на две половины таким образом, что все v <= x для v в массиве.slice(lo, i) для левой стороны и все v > x для v в массиве.slice(i, hi) для правой стороны.

d3.bisector(accessor)
d3.bisector(comparator)

Возвращает бисектор, использующий указанную функцию accessor или comparator. Возвращаемый объект имеет left и right свойства, аналогичные bisectLeft и bisectRight соответственно. Этот метод может использоваться для бисекции массивов объектов вместо ограничений на простые массивы примитивов. Например, задан следующий массив объектов:

var data = [
  {date: new Date(2011, 1, 1), value: 0.5},
  {date: new Date(2011, 2, 1), value: 0.6},
  {date: new Date(2011, 3, 1), value: 0.7},
  {date: new Date(2011, 4, 1), value: 0.8}
];

Подходящая функция бисекции может быть построена как:

var bisect = d3.bisector(function(d) { return d.date; }).right;

Это эквивалентно указанию компаратора:

var bisect = d3.bisector(function(a, b) { return a.date - b.date; }).right;

А затем применено как bisect(data, new Date(2011, 1, 2)), возвращая индекс. Используйте компаратор вместо аксессора, если вы хотите, чтобы значения сортировались в порядке, отличном от естественного порядка, например, в порядке убывания, а не возрастания.

d3.shuffle(массив[, lo[, hi]])

Перемешивает порядок указанного массива с помощью перемешивания Фишера–Йейтса.

Ассоциативные массивы

Другим распространенным типом данных в JavaScript является ассоциативный массив, или проще говоря, объект, который имеет набор именованных свойств. В Java это называется картой, а в Python — словарем. JavaScript предоставляет стандартный механизм для итерации по ключам (или именам свойств) в ассоциативном массиве: цикл for…in. Однако обратите внимание, что порядок итерации не определен. D3 предоставляет несколько операторов для преобразования ассоциативных массивов в стандартные индексированные массивы.

d3.keys(объект)

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

d3.values(объект)

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

d3.entries(объект)

Возвращает массив, содержащий ключи и значения свойств указанного объекта (ассоциативный массив). Каждая запись — это объект со свойствами key и value, например {key: "foo", value: 42}. Порядок возвращаемого массива не определен.

d3.entries({foo: 42, bar: true}); // [{key: "foo", value: 42}, {key: "bar", value: true}]

Карты

Хотя использование обычных объектов в качестве карт в JavaScript может показаться заманчивым, это может привести к непредвиденному поведению, когда используются встроенные имена свойств в качестве ключей. Например, если вы попытаетесь установить object["__proto__"] = 42, это, вероятно, не будет соответствовать вашим ожиданиям. То же самое верно, если вы попытаетесь проверить, определен ли заданный ключ в карте; "hasOwnProperty" in object возвращает true, потому что ваш обычный объект наследует метод hasOwnProperty от прототипа Object. Чтобы избежать этих проблем, ES6 предлагает простые карты и множества; до тех пор, пока современные браузеры не будут поддерживать эти коллекции, вы можете использовать d3.map.

Примечание: в отличие от предлагаемой ES6 карты, d3.map по-прежнему использует строковое приведение для ключей, а не строгое равенство.

d3.map([объект][, ключ])

Создаёт новую карту. Если объект указан, копирует все перечисляемые свойства из указанного объекта в эту карту. Указанный объект может быть массивом. Можно указать опциональную функцию ключ для вычисления ключа для каждого значения в массиве. Например:

var m = d3.map([{name: "foo"}, {name: "bar"}], function(d) { return d.name; });
m.get("foo"); // {"name": "foo"}
m.get("bar"); // {"name": "bar"}
m.get("baz"); // undefined

См. также d3.nest.

map.has(ключ)

Возвращает true тогда и только тогда, когда в этой карте есть запись для указанного строкового ключа. Примечание: значение может быть null или undefined.

map.get(ключ)

Возвращает значение для указанного строкового ключа. Если в карте нет записи для указанного ключа, возвращает undefined.

map.set(ключ, значение)

Устанавливает значение для указанного строкового ключа; возвращает новое значение. Если в карте ранее была запись для того же строкового ключа, старая запись заменяется новым значением.

map.remove(ключ)

Если в карте есть запись для указанного строкового ключа, удаляет запись и возвращает true. В противном случае этот метод ничего не делает и возвращает false.

map.keys()

Возвращает массив строковых ключей для каждой записи в этой карте. Порядок возвращаемых ключей произвольный.

map.values()

Возвращает массив значений для каждой записи в этой карте. Порядок возвращаемых значений произвольный.

map.entries()

Возвращает массив объектов ключ-значение для каждой записи в этой карте. Порядок возвращаемых записей произвольный. Ключ каждой записи — строка, но значение имеет произвольный тип.

map.forEach(функция)

Вызывает указанную функцию для каждой записи в этой карте, передавая ключ и значение записи в качестве двух аргументов. Контекст функции this равен этой карте. Возвращает undefined. Порядок итерации произвольный.

map.empty()

Возвращает true тогда и только тогда, когда в этой карте нет записей.

map.size()

Возвращает количество записей в этой карте.

Множества

d3.set([массив])

Создаёт новое множество. Если массив указан, добавляет заданный массив строковых значений в возвращаемое множество.

set.has(значение)

Возвращает true тогда и только тогда, когда в этом множестве есть запись для указанного строкового значения.

set.add(значение)

Добавляет указанное строковое значение в это множество. Возвращает значение.

set.remove(значение)

Если множество содержит указанное строковое значение, удаляет его и возвращает true. В противном случае этот метод ничего не делает и возвращает false.

set.values()

Возвращает массив строковых значений в этом множестве. Порядок возвращаемых значений произвольный. Может использоваться в качестве удобного способа вычисления уникальных значений для набора строк. Например:

d3.set(["foo", "bar", "foo", "baz"]).values(); // "foo", "bar", "baz"
set.forEach(функция)

Вызывает указанную функцию для каждого значения в этом множестве, передавая значение в качестве аргумента. Контекст функции this равен этому множеству. Возвращает undefined. Порядок итерации произвольный.

set.empty()

Возвращает true тогда и только тогда, когда в этом множестве нет значений.

set.size()

Возвращает количество значений в этом множестве.

Операторы для массивов

d3.merge(массивы)

Объединяет указанные массивы в один массив. Этот метод похож на встроенный метод array concat; единственное отличие заключается в том, что он более удобен, когда у вас есть массив массивов.

d3.merge([ [1], [2, 3] ]); // returns [1, 2, 3]
d3.range([начало, ]окончание[, шаг])

Генерирует массив, содержащий арифметическую прогрессию, аналогично встроенной функции Python range. Этот метод часто используется для итерации по последовательности числовых или целых значений, таких как индексы в массиве. В отличие от версии Python, аргументы не обязаны быть целыми числами, хотя результаты более предсказуемы, если они являются, из-за точности с плавающей запятой. Если шаг опущен, он по умолчанию равен 1. Если начало опущено, он по умолчанию равен 0. Значение окончание не включается в результат. Полная форма возвращает массив чисел [начало, начало + шаг, начало + 2 * шаг, …]. Если шаг положительный, последнее значение — это наибольшее начало + i * шаг, меньшее окончание; если шаг отрицательный, последнее значение — это наименьшее начало + i * шаг, большее окончание. Если возвращаемый массив содержал бы бесконечное число значений, вместо создания бесконечного цикла генерируется ошибка.

d3.permute(массив, индексы)

Возвращает перестановку указанного массива, используя указанный массив индексов. Возвращаемый массив содержит соответствующий элемент в массиве для каждого индекса в индексах, в порядке. Например, permute(["a", "b", "c"], [1, 2, 0]) возвращает ["b", "c", "a"]. Допустимо, чтобы массив индексов имел длину, отличную от массива элементов, и для индексов были дублированы или опущены.

Этот метод также может использоваться для извлечения значений из объекта в массив с устойчивым порядком. (Индексы массива в JavaScript — это просто свойства, которые имеют особые отношения к .length.) Извлечение значений с ключами в порядке может быть полезным для генерации массивов данных в вложенных выделениях. Например, мы могли бы отобразить некоторые данные о урожае ячменя Миннесоты выше в табличной форме:

var cols = ["site", "variety", "yield"];
thead.selectAll('th').data(cols)
    .enter().append('th').text(function (d) { return d.toUpperCase(); });
tbody.selectAll('tr').data(yields)
    .enter().append('tr').selectAll('td').data(function (row) { return d3.permute(row, cols); })
        .enter().append('td').text(function (d) { return d; });
d3.zip(массивы…)

Возвращает массив массивов, где i-й массив содержит i-й элемент из каждого из аргументных массивов. Возвращаемый массив усекается по длине до кратчайшего массива в массивах. Если массивы содержат только один массив, возвращаемый массив содержит массивы по одному элементу. Без аргументов возвращаемый массив пуст.

d3.zip([1, 2], [3, 4]); // returns [[1, 3], [2, 4]]
d3.транспонировать(матрица)

Эквивалентно d3.zip.apply(null, matrix); использует оператор zip как двумерную [транспонирование матрицы.

d3.пары(массив)

Для каждой смежной пары элементов в указанном массиве возвращает новый массив кортежей элемента i и элемента i - 1. Например:

d3.pairs([1, 2, 3, 4]); // returns [[1, 2], [2, 3], [3, 4]]

Если указанный массив содержит меньше двух элементов, возвращает пустой массив.

Группировка

Группировка позволяет группировать элементы в массиве в иерархическую древовидную структуру; представьте себе оператор GROUP BY в SQL, за исключением того, что у вас может быть несколько уровней группировки, а результирующий вывод — дерево, а не плоская таблица. Уровни в дереве задаются функциями ключей. Листовые узлы дерева могут быть отсортированы по значению, а внутренние узлы — по ключу. Дополнительная функция сводки будет сводить элементы в каждом листовом узле с помощью функции сводки. Оператор группировки (объект, возвращаемый d3.nest) является многократно используемым и не сохраняет никаких ссылок на данные, которые группируются.

Например, рассмотрим следующую табличную структуру данных о урожае ячменя с разных участков в Миннесоте в период 1931-2:

var yields = [
  {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
  {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
  {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"},
  ...
];

Для облегчения визуализации может быть полезно сначала сгруппировать элементы по году, а затем по сортам, как показано ниже:

var nest = d3.nest()
    .key(function(d) { return d.year; })
    .key(function(d) { return d.variety; })
    .entries(yields);

Это возвращает вложенный массив. Каждый элемент внешнего массива — это пара ключ-значение, перечисляющая значения для каждого уникального ключа:

[{key: "1931", values: [
   {key: "Manchuria", values: [
     {yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
     {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
     {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"}, ...]},
   {key: "Glabron", values: [
     {yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm"},
     {yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca"}, ...]}, ...]},
 {key: "1932", values: ...}]

Вложенная форма позволяет легко итерировать и генерировать иерархические структуры в SVG или HTML.

Для более подробного введения в d3.nest см.:

  • Учебник и примеры d3 Nest от Фобьи Брайт http://bl.ocks.org/phoebebright/raw/3176159/
  • Мистер Нестер от Шан Картера http://bl.ocks.org/shancarter/raw/4748131/
d3.группировка()

Создает новый оператор группировки. Набор ключей изначально пуст. Если оператор map или entries вызывается до регистрации каких-либо функций ключей, оператор группировки просто возвращает входной массив. Примеры группировки: http://bl.ocks.org/phoebebright/raw/3176159/

nest.ключ(функция)

Регистрирует новую функцию ключа. Функция ключа будет вызываться для каждого элемента во входном массиве и должна возвращать строковый идентификатор, который используется для назначения элемента его группе. Чаще всего функция реализуется как простой аксессор, например, аксессоры года и сорта в приведенном выше примере. Функция не получает индекс входного массива. Каждый раз, когда регистрируется ключ, он добавляется в конец внутреннего массива ключей, и результирующая карта или записи будут иметь дополнительный уровень иерархии. В настоящее время нет возможности удалить или запросить зарегистрированные ключи. Последний зарегистрированный ключ называется текущим ключом в последующих методах.

nest.сортировать ключи(компаратор)

Сортирует значения ключей для текущего ключа с использованием указанного компаратора, например, d3.descending. Если для текущего ключа не указан компаратор, порядок, в котором будут возвращены ключи, не определен. Обратите внимание, что это влияет только на результат оператора записей; порядок ключей, возвращаемых оператором карты, всегда не определен, независимо от компаратора.

var nest = d3.nest()
    .key(function(d) { return d.year; })
    .sortKeys(d3.ascending)
    .entries(yields);
nest.сортировать значения(компаратор)

Сортирует листовые элементы с использованием указанного компаратора, например, d3.descending. Это примерно эквивалентно сортировке входного массива до применения оператора группировки; однако это, как правило, более эффективно, так как размер каждой группы меньше. Если компаратор значений не указан, элементы будут возвращены в том порядке, в котором они появились во входном массиве. Это относится как к операторам map, так и к операторам entries.

nest.сворачивать(функция)

Указывает функцию сводки функция, которая должна применяться к каждой группе листовых элементов. Возвращаемое значение функции сводки заменит массив листовых значений как в ассоциативном массиве, возвращаемом оператором map, так и в атрибуте values каждой записи, возвращаемой оператором entries.

nest.map(массив[, тип карты])

Применяет оператор группировки к указанному массиву, возвращая ассоциативный массив. Каждая запись в возвращаемом ассоциативном массиве соответствует уникальному значению ключа, возвращаемому первой функцией ключа. Значение записи зависит от количества зарегистрированных функций ключей: если есть дополнительный ключ, значение — это другой вложенный ассоциативный массив; в противном случае значение — массив элементов, отфильтрованных из входного массива, которые имеют данное значение ключа.

Если указан тип карты, указанная функция используется для построения карты вместо возвращения простого JavaScript-объекта. Рекомендуется использовать d3.map для этой цели. Например:

var yieldsByYearAndVariety = d3.nest()
    .key(function(d) { return d.year; })
    .key(function(d) { return d.variety; })
    .map(yields, d3.map);

Использование d3.map вместо объекта обеспечивает удобство (например, возвращаемая карта имеет функции keys и values) и защищает от необычных имён ключей, которые конфликтуют со встроенными JavaScript-свойствами, такими как __proto__.

nest.записи(массив)

Применяет оператор группировки к указанному массиву, возвращая массив записей ключ-значение. По сути, это аналогично применению d3.entries к ассоциативному массиву, возвращаемому map, но это применяется ко всем уровням иерархии, а не только к первому (внешнему) уровню. Каждая запись в возвращаемом массиве соответствует уникальному значению ключа, возвращаемому первой функцией ключа. Значение записи зависит от количества зарегистрированных функций ключей: если есть дополнительный ключ, значение — это другой вложенный массив записей; в противном случае значение — это массив элементов, отфильтрованных из входного массива, которые имеют данное значение ключа.

© 2010–2016 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-3.x-api-reference/blob/master/Arrays.md

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API