WedX - журнал о программировании и компьютерных науках

Есть ли обозначения для динамических индексов в литералах массива?

При объявлении литералов объектов можно объявлять динамические ключи следующим образом:

const foo = 'foo';

const obj = {
  [foo]: 'bar'
}

console.log(obj);

Этот синтаксис не работает для массивов, потому что квадратная скобка интерпретируется как объявление массива, а анализатор завершается ошибкой при достижении двоеточия. Пример использования: клонирование массива при изменении последнего элемента:

const arr = [1, 2, 3];

const modifiedClone = [...arr, [arr.length - 1]: 4]; // Fails

Есть ли синтаксис для объявления динамических индексов для литералов массива?


  • С литералом массива вы можете объявить массив только с его элементами. На самом деле вы не можете сделать то же самое, что и распространение объекта, потому что фундаментальный синтаксис массива не работает таким образом — вы не определяете элементы по их положению, вы просто определяете последовательность, которая превращается в массив. 04.12.2020
  • Просто напишите const modifiedClone = [...arr]; modifiedClone[arr.length - 1] = 4;? 04.12.2020
  • @Bergi Берги да, очевидно, но мой вопрос касается одной инструкции для достижения этой цели. 04.12.2020
  • Вы можете поместить все в IIFE, если хотите сделать это одним выражением :-) 04.12.2020
  • Я предпочитаю ответ Нины Шольц! 04.12.2020
  • Существует предложение, которое позволит вам пропускать и перематывать итераторы. При этом можно было бы быть более гибким и/или использовать помощники итераторов. Если вы хотите одновременно распространять и перезаписывать, вы можете использовать для этого генераторы. Стоит ли это того, зависит, но это вариант. 04.12.2020

Ответы:


1

Вы можете использовать Object.assign с пустой массив в качестве цели и заданный массив и объект со свойством индекса.

const arr = [1, 2, 3];

const modifiedClone = Object.assign([], arr, { [arr.length - 1]: 4 }); 

console.log(modifiedClone);

04.12.2020

2

То, о чем вы просите, в настоящее время невозможно с использованием литерала массива и синтаксиса распространения. Это связано с тем, что, в отличие от литералов объектов, массив определяется не конкретными индексами, а последовательностью, которая становится его элементами.

В лучшем случае вы можете использовать elision, чтобы оставить индекс пустым, например, [1, , 3] создаст 1, <empty>, 3, но вы все равно должны указать это явно, вы не можете пропустить, это означает, что создание массива только с первым и десятым элементом становится очень сложным [1,,,,,,,,,10]. Определенно не рекомендуется иметь больше в качестве литерала массива.

При этом синтаксис распространения ... с массивами принимает значения из итератор, поэтому [...arr] похож на:

let result = [];
let it = arr[Symbol.iterator]();
let next = it.next();

while (!next.done)) {
    result.push(next.value);
    next = it.next();
}

Зная это, мы можем использовать функции-генераторы и создайте несколько простых общих вспомогательных генераторов, которые преобразуют итерацию и распространяют свои результаты. Например

Получить все, кроме последнего элемента, из итерации:

/** 
 * 
 * @generator
 * @param {Iterable}
 * @yields {*} every value from the iterable but the last one
 */
function* initial(iterable) {
  const it = iterable[Symbol.iterator]();
  let last = it.next();
  let next = it.next();
  
  while(!next.done){
    yield last.value;
    last = next;
    next = it.next();
  }
}


const arr = [1, 2, 3];
const modifiedClone = [...initial(arr), 4];

console.log(modifiedClone);

Возьмите первые значения num из итерации:

/**
 *
 * @generator
 * @param {number} num - how many items to extract
 * @param {Iterable} itearable - iterable from where the results should be extracted
 * @yields {*} - at most `num` amount of results from `iterable`
 */
function* take(num, iterable) {
  const it = iterable[Symbol.iterator]();
  
  let {value, done} = it.next();
  for (let i = 0; i < num && !done; i++, {value, done} = it.next()) {
    yield value;
  }
}

const arr = [1, 2, 3];
const modifiedClone = [...take(arr.length - 1, arr), 4];

console.log(modifiedClone);

Перейдите к итерации и преобразуйте значение там, где это необходимо:

/**
 * transform an iterable of key-value pairs by their key
 * 
 * @generator
 * @param {Map} replacements - new values for each of the keys
 * @param {Iterable} keyValueIterable - iterable which produces `[key, value]` pairs
 * @yields {*} - the values of the iterable transformed where needed
 */
function* replaceByKey(replacements, keyValueIterable) {
  const it = keyValueIterable[Symbol.iterator]();

  for (let {value: pair, done} = it.next(); !done; {value: pair, done} = it.next()) {
    let [key, value] = pair;
    if (replacements.has(key))
      yield replacements.get(key);
    else
      yield value;
  }
}

const arr = ["a", "b", "c", "d", "e"];

const replace = new Map()
  .set(1, "foo")
  .set(arr.length-1, "bar");
const modifiedClone = [...replaceByKey(replace, arr.entries())];

console.log(modifiedClone);

Дополнительные возможности доступны в зависимости от того, что вам нужно.

04.12.2020
Новые материалы

Объяснение документов 02: BERT
BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


Для любых предложений по сайту: [email protected]