簡體   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