Как вставить значения из массива в объект, используя JavaScript? - PullRequest
1 голос
/ 20 июня 2020

Я хотел бы извлечь значения из объекта (готово), которые помещаются в массив (готово), затем эти значения изменяются (с помощью библиотеки анимации) и возвращаются мне как массив значений.

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

Но я застрял на чем-то довольно основном c и определенно выполнимом.

У меня есть пример состояния, вроде этого (это может быть совершенно другая форма, это просто пример):

var state = { 
  ignore: "me",
  count: 0,
  foo: 10,
  bar: {
    baz: 99
  }
}

У меня есть новое состояние, которое я хочу передать в анимацию метод:

var newState = { 
  count: 100,
  foo: 50,
  bar: {
    baz: 999
  }
}

В методе tweenState есть библиотека tween, которая создает массив этих значений в каждом «кадре» анимации:


// NOTE: I only pass in the properties I wanna tween!!

myApp.tweenState({ count: 100, foo: 50, bar: { baz: 999 } })

// internally, the tween lib produces something like this on each frame:

tweenedValues = [ 50.1231, 34.43543, 456.4543 ]

Я бы хотел чтобы вставить эти промежуточные значения в объект той же формы, что и объект состояния, который я использую, чтобы создать это в каждом кадре (как в приведенном выше примере состояния):

tweenedState = { 
  ignore: "me",
  count: 50.1231,
  foo: 34.43543,
  bar: {
    baz: 456.4543
  }
}

... пока что, У меня только этот ужасный код (вызывается в каждом кадре):

  // make sure tweened values are in an array
  var valuesArr = Array.isArray(tweenedValues) ? tweenedValues : [tweenedValues]
  // this object will hold tween values of current frame/progress, 
  // set to original state for now... we'll update it's values from 
  // valuesArr later
  var tweenedState = self.state
  // set the newState properties with new values from valuesArr
  // (newState is the state passed into the tweenState() method)
  Object.keys(newState).forEach((key, index) => {
    if (typeof newState[key] === "object") {
      Object.keys(newState[key]).forEach(key2 => {
        tweenedState[key][key2] = valuesArr[index]
      })
    } else {
      tweenedState[key] = valuesArr[index]
    }
  })
  console.log("tweenedState: ", tweenedState)
* 10 22 * Что имеет следующие очевидные проблемы:
  • не рекурсивно, не может go глубже, чем на 2 уровня в объекте
  • в любом случае строка tweenedState[key][key2] = valuesArr[index] не не установил ожидаемое значение
  • , когда я превратил его в рекурсивную функцию, он зацикливался навсегда и разбился

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

EDIT: Очевидно, объект состояния может выглядеть совершенно по-другому - приведенный является просто примером - Это может быть многоуровневая глубина и может содержать другие вещи, НЕ переданные в .. Ключевым моментом является то, что я получаю объект состояния, точно такой же, как исходный, но с вставленными вместо него промежуточными значениями.

И я повторяю - библиотека Tween создает массив значений, а не я, не мой выбор. И да, я знаю, что свойства объектов не всегда находятся в одном и том же порядке.

РЕДАКТИРОВАТЬ 2: этот код должен быть изоморфным c - работать в последних браузерах (не заботится о IE) и Node 10 или новее, в идеале без полифиллов ...

РЕДАКТИРОВАТЬ 3: ТЕПЕРЬ РЕШЕНО:

И NinaScholz, и mashi предоставили ответы, которые сработали для меня (после того, как я исправил ошибку

Ответ Ninas имеет более строгие требования к версии JS и немного менее переносим, ​​чем ответ mashis. На этом основании я принял ответ маши, хотя ответ Нинас тоже очень хорош.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 21 июня 2020

function setTweenedValues(state, values) {
  const reducer = (newState, [key, val]) => {
    newState[key] = val;
    if (typeof val === "number") {
      newState[key] = values.shift();
    }
    if (typeof val === "object") {
      newState[key] = Object.entries(val).reduce(reducer, {});
    }

    return newState;
  };

  const newState = Object.entries(state).reduce(reducer, {});

  return newState;
}

var state = { count: 200, foo: 10, bar: { zzz: 999 }, ignore: "me" },
    tweenedValues = [50.1231, 34.43543, 456.4543],
    tweenedState = setTweenedValues(state, [...tweenedValues]);

console.log(tweenedState);
2 голосов
/ 20 июня 2020

Вы можете перебирать записи и снова вызывать функцию для вложенных записей.

function setValues(pattern, values) {
    return Object.fromEntries(Object
        .entries(pattern)
        .map(([k, v]) => [
            k,
            v && typeof v === 'object'
                ? setValues(v, values)
                : values.length ? values.shift() : v
        ])
    );
}

var state = { count: 200, foo: 10, bar: { zzz: 999 }, ignore: "me" },
    tweenedValues = [50.1231, 34.43543, 456.4543],
    tweenedState = setValues(state, [...tweenedValues]);

console.log(tweenedState);
0 голосов
/ 20 июня 2020

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

const [count, foo, bar] = tweenedValues;

, затем сделайте объект вроде этого

let obj = {count, foo, bar}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...