繁体   English   中英

JavaScript使用lodash将对象数组转换为另一个对象

[英]JavaScript transform array of objects into another using lodash

我有一个对象数组,如下所示:

[
  {
    type: 'car',
    choices: [
      'audi',
      'honda',
      'bmw',
      'ford'
    ],
  },
  {
    type: 'drink',
    choices: [
      'soda',
      'water',
      'tea',
      'coffee'
    ],
  },
  {
    type: 'food',
    choices: [
      'chips',
      'pizza',
      'cookie',
      'pasta'
    ],
  }
]

使用lodash如何将其转换为如下所示的内容:

[
  {
    question: [
      {
        drink: "tea"
      },
      {
        car: "bmw"
      }
    ]
  },
  {
    question: [
      {
        food: "cookie"
      },
      {
        car: "ford"
      }
    ]
  },
  {
    question: [
      {
        drink: "soda"
      },
      {
        food: "pizza"
      }
    ]
  },
  {
    question: [
      {
        food: "chips"
      },
      {
        drink: "water"
      }
    ]
  },
  {
    question: [
      {
        car: "audi"
      },
      {
        food: "pasta"
      }
    ]
  },
  {
    question: [
      {
        car: "honda"
      },
      {
        drink: "coffee"
      }
    ]
  },
]

逻辑如下:

  • 每个问题都有2种选择的组合,其中每种选择都是不同类型的例子(汽车和食品)。
  • 不同类型的组合应该只发生两次(汽车,食物)。
  • 没有重复的选择。
  • 选择的选择应该是随机的。

我尝试使用此函数展平数组

    let flattenItems = _.flatMap(items, ({ type, choices}) =>
      _.map(choices, choice => ({
        question: [
          { type: type, choice: choice },
          { type: type, choice: choice }
        ],
      })
    ));

但这不是我需要的,而且不是随机的。 我不确定我的方法是否正确,我想我应该使用过滤器或减少

任何有关如何解决这个的帮助将不胜感激使用JS或lodash将是好的。

您可以从types和随机choices获得组合,并选中是否使用了值。

 function getCombinations(array, size) { function c(left, right) { function getQuestion({ type, choices }) { var random; do { random = choices[Math.floor(Math.random() * choices.length)]; } while (taken.get(type).has(random)) taken.get(type).add(random); return { [type]: random }; } left.forEach((v, i, a) => { var temp = [...right, v]; if (temp.length === size) { result.push({ question: temp.map(getQuestion) }); } else { c([...a.slice(0, i), ...a.slice(i + 1)], temp); } }); } var result = [], taken = new Map(array.map(({ type }) => [type, new Set])); c(array, []); return result; } var data = [ { type: 'car', choices: ['audi', 'honda', 'bmw', 'ford'] }, { type: 'drink', choices: ['soda', 'water', 'tea', 'coffee'] }, { type: 'food', choices: ['chips', 'pizza', 'cookie', 'pasta'] } ]; console.log(getCombinations(data, 2)); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

使用Lodash

 function randomizedQues(items) { let result = []; let flattenItems = _.flatMap(items, ({ type, choices }) => _.map(choices, choice => ({ type: type, choice: choice }) )) while(flattenItems.length > 1) { let r1 = _.random(flattenItems.length - 1), e1 = flattenItems[r1]; let r2 = _.random(flattenItems.length - 1), e2 = flattenItems[r2]; if(e1.type === e2.type) continue result.push({ question: [ {[e1.type]: e1.choice}, {[e2.type]: e2.choice} ] }) _.pullAt(flattenItems, [r1, r2]) } return result } let items = [{"type":"car","choices":["audi","honda","bmw","ford"]},{"type":"drink","choices":["soda","water","tea","coffee"]},{"type":"food","choices":["chips","pizza","cookie","pasta"]}] console.log(randomizedQues(items)) 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

这是我的想法,每种不同类型的组合需要出现两次。 所以我在数组上循环前进,并将每种类型与前进类型组合在一起。 然后我在数组上向后循环,并将每种类型与前面的类型组合在一起。 与此同时,我使用Math.random()choices子阵列中选择一个随机选择。 唯一的问题是,这不会强制执行严格的重复删除,但依赖于RNG来保证重复的可能性较低。 在创建新问题之前,您应该能够在每个循环中添加重复的检查代码。

 function buildQuestions(data) { const questions = [] for (let i = 0; i < data.length; i++) for (let j = i + 1; j < data.length; j++) questions.push({question: [{[data[i].type]: data[i].choices[Math.round(Math.random() * (data[i].choices.length - 1))]}, {[data[j].type]: data[j].choices[Math.round(Math.random() * (data[j].choices.length - 1))]}]}) for (let i = data.length - 1; i > 0; i--) for (let j = i - 1; j >= 0; j--) questions.push({question: [{[data[i].type]: data[i].choices[Math.round(Math.random() * (data[i].choices.length - 1))]}, {[data[j].type]: data[j].choices[Math.round(Math.random() * (data[j].choices.length - 1))]}]}) return questions } const choices = [{ type: 'car',choices: ['audi','honda','bmw','ford'],},{type: 'drink', choices: ['soda','water','tea','coffee'],},{type: 'food',choices: ['chips','pizza','cookie','pasta'],}] console.log(buildQuestions(choices)) 

您可以使用递归函数继续从每个数组中删除项目,直到您没有剩余足够的选项来填写任何其他问题。

为了做到这一点,我们有一些函数接收一个数组,并返回一个随机项,加上没有该项的数组。 然后,我们可以使用该数据构建问题,确保每个项目仅使用一次。

 const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x) const data = [ { type: 'car', choices: ['audi', 'honda', 'bmw', 'ford'] }, { type: 'drink', choices: ['soda', 'water', 'tea', 'coffee'] }, { type: 'food', choices: ['chips', 'pizza', 'cookie', 'pasta'] } ]; const getArrayIndexPair = array => [ array, getRandom(array), ]; const subtractItemFromArray = ([array, index]) => [ array.slice(index, index + 1)[0], [ ...array.slice(0, index), ...array.slice(index + 1, array.length) ] ]; const getRandom = array => Math.floor(Math.random()*array.length); const takeRandom = pipe( getArrayIndexPair, subtractItemFromArray, ); const choicesKeyedByType = data .reduce((p, c) => ({ ...p, [c.type]: c.choices, }), {}) const formQuestions = (choices, questions=[]) => { if (Object.keys(choices).length <= 1) { return questions; } const [keyOne, remainingKeys] = takeRandom(Object.keys(choices)); const [keyTwo] = takeRandom(remainingKeys); const [choiceOne, remainingKeyOneChoices] = takeRandom(choices[keyOne]); const [choiceTwo, remainingKeyTwoChoices] = takeRandom(choices[keyTwo]); const newChoices = { ...choices, [keyOne]: remainingKeyOneChoices, [keyTwo]: remainingKeyTwoChoices, }; const newChoicesWithoutEmpty = Object.keys(newChoices) .filter(key => newChoices[key].length > 0) .reduce((p, c) => ({ ...p, [c]: newChoices[c] }), {}); const newQuestions = [ ...questions, { [keyOne]: choiceOne, [keyTwo]: choiceTwo, } ]; return formQuestions( newChoicesWithoutEmpty, newQuestions, ); }; console.dir(formQuestions(choicesKeyedByType)) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM