Встроенный массив разбора с несколькими типами

1

У меня есть источник данных вне моего контроля, который дает мне массив с разными типами данных, которые мне нужно обрабатывать перед использованием. Реальный источник данных имеет более двух типов данных, но они всегда в одном и том же известном порядке.

В настоящее время я использую промежуточное значение (rawValues), но очень хотел бы избежать этого.

const rawValues = getData(); // e.g. ["12.5", "42", "hello"]

const [num1, num2, text] = [
  Number(rawValues[0]), 
  Number(rawValues[1]), 
  rawValues[2]
];

Единственный встроенный параметр, который я знаю, будет несколько грязным .map() например:

const [num1, num2, text] = getData()
  .map((data, i) => i < 2 ? Number(data) : data);

Я хотел бы также, чтобы избежать "магического числа 2" и обоснованную unreadability этого подхода.

Я подумал о простом тестировании слабого равенства каждого элемента массива для способности coerce (Number(data) == data) на карте, например

const [num1, num2, text] = getData()
  .map((data, i) => Number(data) == data ? Number(data) : data);

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

Просто повторю свой вопрос - какой лучший (или самый идиоматический) способ справиться с этими входящими данными, желательно без создания временных переменных? Речь идет не о гольф-играх (я не беспокоюсь о # строках кода), а о читаемом коде, который позволяет избежать области загрязнения с помощью значения temp.

  • 0
    Почему заказ зафиксирован?
  • 1
    Вы можете использовать ES6 деструктуризацию массива.
Показать ещё 1 комментарий
Теги:
arrays

3 ответа

3
Лучший ответ

Я бы представлял известные типы как массив типов (которые являются конструкторами, которые можно назвать):

const types = [Number, Number, String];

затем обрабатывать входящие данные как

const [num1, num2, text] = getData().map((x, i) => types[i](x));

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

  • 0
    Благодарю. На сегодняшний день это кажется наиболее читаемым и гибким ответом. Это все еще имеет промежуточное значение, но это не то, что просто копия данных. Я бы никогда не подумал сделать это таким образом и был бы счастлив узнать новый подход!
  • 0
    Также можно использовать .shift() для массива типов и устранить необходимость в индексе: const cooked = raw.map(x => types.shift()(x));
Показать ещё 4 комментария
1

они всегда в одном и том же известном порядке

Вы можете распаковать массив из getData в свойства объекта результата.

let getData = function(){ return ["12.5", "42", "hello"]; }

let result = {};
[result["float"],result["int"],result["string"]] = getData();

console.log(result);

Я был не уверен, что вы хотите, чтобы имена свойств были. Они могут быть просто num1, num2, string. Именование, к тому же, я думаю.

  • 0
    Благодарю. Это также хороший подход, который я не рассматривал. Это не приводит значения к соответствующим типам, но это не будет сложным шагом для добавления.
  • 0
    @BenFletcher - у меня сложилось впечатление, что типы известны, если это так, вы всегда можете отобразить типы в правой части выражения, как показано в некоторых других ответах здесь.
1
 const [num1, num2, text] = getData().map(n => !n || isNaN(+n) ? n : +n);

Или же:

let [num1, num2, text] = getData();
num1 = +num1;
 num2 = +num2;
  • 0
    +n || n); что делает эта часть?
  • 0
    @kunal парсится с числом, если это возможно, иначе возьмите строку
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню