заполнить массив 4 случайными различными неповторяющимися объектами с некоторыми фильтрами ES6 + - PullRequest
1 голос
/ 26 февраля 2020

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

пример JSON с рецептами

[
  {
    recipeId: 1,
    recipeTypeId: 1, // breakFast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
]

это моя функция:

randomRecipes() {
  // previously saved recipes from api
  localStorage.getItem('recipesList');
  // random generator
  const randomIndex = new Set();
  const recommendedRandomRecipes: [] = [];
  while (randomIndex.size < 4) {
    randomIndex.add(Math.floor(Math.random() * recipes.length));
  }
  randomIndex.forEach(i => recommendedRandomRecipes.push(recipes[Number(i)]));
  localStorage.addItem('recommendedRecipes', recommendedRandomRecipes);
  this.recipes = recommendedRandomRecipes;
}

результат, который я хочу:

recommendedRandomRecipes [1,2,3,4] or [2,3,4,5]

что я не хочу

recommendedRandomRecipes [1,2,3,5] // 2 breakfast in the array

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

Пояснения в фрагменте кода, пожалуйста, посмотрите

var recipes = [
  {
    recipeId: 1,
    recipeTypeId: 1, // breakFast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
]

function randomRecipes(recipes) {
  // 1. taking a count of all the  different recipeTypeIds, it could be not always 4. could be 3, could be 5, so
  var recipeTypeIdsLegth = recipes.reduce((acc, item) => acc.indexOf(item.recipeTypeId) == -1 ? [...acc, item.recipeTypeId] : acc, []).length;
  console.log(recipeTypeIdsLegth) // 4

  // 2. clone original array, because we will play and modify it
  let clonedRecipes = [...recipes]

  // 3 declaring a result arrray
  var recommendedRandomRecipes = []

  // 4. create a loop
  for (i = 0; i < recipeTypeIdsLegth; i++) {
    
    // 5. randomindex
    var randomIndex = Math.floor(Math.random() * clonedRecipes.length);

    // 6. push recipe to result array
    recommendedRandomRecipes.push(clonedRecipes[randomIndex]);

    // 7. main magic. remove all the recipies with the same clonedRecipes[randomIndex].recipeTypeId from clonedRecipes
    clonedRecipes = clonedRecipes.filter(item => item.recipeTypeId !== clonedRecipes[randomIndex].recipeTypeId)
  }

  // 8. returning
  return recommendedRandomRecipes;
}

var recommendedRandomRecipes = randomRecipes(recipes);

console.log(recommendedRandomRecipes);
1 голос
/ 26 февраля 2020

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

  1. Чтобы вместить произвольное число recipeTypeId, мы сначала перебираем массив и собираем все уникальные значения. Это можно сделать, используя new Set() и добавив их к нему
  2. Затем мы переберем этот уникальный набор типов рецептов. Для каждого набора мы генерируем отфильтрованный массив (из исходного списка рецептов), который содержит все рецепты для данного типа рецепта. Затем мы выбираем оттуда случайный предмет .
  3. Собираем все эти предметы и только возвращаем их recipeId
  4. При желании сортируем их в порядке возрастания (как желаемый результат предлагает).

См. подтверждение концепции:

const recipesList = [
  {
    recipeId: 1,
    recipeTypeId: 1, // breakFast
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 2,
    recipeTypeId: 2, // lunch
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 3,
    recipeTypeId: 3, // snack
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 4,
    recipeTypeId: 4, // dinner
    "description": "someRecipe",
    "img": "someImgBase64",
  },
  {
    recipeId: 5,
    recipeTypeId: 1, // breakfast
    "description": "someRecipe",
    "img": "someImgBase64",
  }
];

// Collect unique recipeTypeId
const recipeTypes = new Set();
recipesList.forEach((recipe) => recipeTypes.add(recipe.recipeTypeId));

// Go through unique recipe types and return a randomly chosen recipe
const recipeCombos = Array.from(recipeTypes).map((type) => {
  const filteredRecipesByType = recipesList.filter((recipe) => {
    return recipe.recipeTypeId === type;
  });
  
  // Retrieve random recipe in this filtered collection
  const randomRecipeByType = filteredRecipesByType[Math.floor(Math.random() * filteredRecipesByType.length)];
  
  // Since you only want the recipeId, we return that property only
  return randomRecipeByType.recipeId;
});

// For your given data, the only possible combinations are:
// [1,2,3,4]
// [2,3,4,5]
console.log(recipeCombos.sort());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...