如何将这两个功能合而为一?

时间:2019-04-16 09:14:13

标签: javascript function

我正在尝试创建一个数组,其中的数据来自内部包含5个数组的大数组。 问题是我的函数重复了5次,因为我需要为每个数组做一个随机函数以从每个数组中获取2个itema,然后进行合并以创建最终的10个数组。

这是一个大数组,里面还有3个数组:

var question = [
   CP = [
      { questionNumber: "1", type: "CP", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "2", type: "CP", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "3", type: "CP", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "4", type: "CP", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "5", type: "CP", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ],
    NP = [
      { questionNumber: "6", type: "NP", question: "quien es mas wapo?", answer1: "yo", answer2:"javier"},
      { questionNumber: "7", type: "NP", question: "te gusta viajar?", answer1: "si", answer2:"no"},
      { questionNumber: "8", type: "NP", question: "eres romantico?", answer1: "si", answer2:"a veces"},
      { questionNumber: "9", type: "NP", question: "que te gusta mas?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "10", type: "NP", question: "eres mas...", answer1: "dormilon", answer2:"hablador"}
   ]];

这是2个功能:

var CPselected = [];
for (var i = 0; i < 2; i++){
    rand();
}
function rand(){
    var ran = CP[Math.floor(Math.random() * CP.length)];  
    if (CPselected.indexOf(ran) == -1)
        CPselected.push(ran);
    else
         rand();
}



var NPselected = [];
for (var i = 0; i < 2; i++){
    NPrand();
}
function NPrand(){
    var ran = NP[Math.floor(Math.random() * NP.length)];  
    if (NPselected.indexOf(ran) == -1)
        NPselected.push(ran);
    else
         NPrand();
}

最后我表示同意:

var Selected = CPselected.concat(NPselected);

3 个答案:

答案 0 :(得分:1)

要解决您收到的有关question声明语法的评论。通常,在javascript中,我们定义如下对象:

{
  a: [1, 2, 3],
  b: 'hello, world],
}

在您的问题中,您还有类似的内容:

[
  a = [1, 2, 3],
  b = 'hello, world',
]

这将创建一个数组,而不是一个对象,并且只能工作并具有所需的数据,因为在javascript中,赋值操作返回赋值的右侧,例如:

a = 'hello, world'

返回“你好,世界”。

您拥有的有效语法,但这非常不寻常。


回到您的实际问题。

这应该可以满足您的需求。该代码将所有question个项目合并到一个数组中,然后将一个随机项目转移到一个新列表中,直到原始列表中没有任何项目为止。

var question = [
   CP = [
      { questionNumber: "1", type: "CP", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "2", type: "CP", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "3", type: "CP", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "4", type: "CP", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "5", type: "CP", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ],
    NP = [
      { questionNumber: "6", type: "NP", question: "quien es mas wapo?", answer1: "yo", answer2:"javier"},
      { questionNumber: "7", type: "NP", question: "te gusta viajar?", answer1: "si", answer2:"no"},
      { questionNumber: "8", type: "NP", question: "eres romantico?", answer1: "si", answer2:"a veces"},
      { questionNumber: "9", type: "NP", question: "que te gusta mas?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "10", type: "NP", question: "eres mas...", answer1: "dormilon", answer2:"hablador"}
   ]];

const getRandomIndex = list => Math.floor(Math.random() * list.length)
const removeArrayItemAtIndex = (list, index) => [
   ...list.slice(0, index),
   ...list.slice(index + 1, list.length),
];

const randomSortTick = (listA, listB) => {
  const indexToTransfer = getRandomIndex(listA);
  return [
     removeArrayItemAtIndex(listA, indexToTransfer),
     [
       ...listB,
       listA[indexToTransfer],
     ],
  ]
}

const transferArrays = (listA, listB, transferFunction) =>
  listA.length > 0 ?
    transferArrays(...transferFunction(listA, listB), transferFunction) :
    [listA, listB]
    
const randomlySortQuestions = questions =>
  transferArrays(
    [...questions[0], ...questions[1]],
    [],
    randomSortTick
  )[1]

console.dir(
  randomlySortQuestions(question)
)

答案 1 :(得分:0)

首先,您显示的question数组不是有效的JavaScript语法,因此导致了SyntaxError 编辑那是不对的。确实可以。

但是,由于您的问题更多是关于将两个功能合并为一个:

查看您已经拥有的功能,并确定将它们与其他功能区分开的地方。以获得更好的概述:

function rand(){
  var ran = CP[Math.floor(Math.random() * CP.length)];  
  if (CPselected.indexOf(ran) == -1)
    CPselected.push(ran);
  else
    rand();
}

// ... Left out for brevity ...

function NPrand(){
  var ran = NP[Math.floor(Math.random() * NP.length)];  
  if (NPselected.indexOf(ran) == -1)
    NPselected.push(ran);
  else
    NPrand();
}

它们两者的功能完全相同(计算随机Number,根据该数字从一个已经存在的Array中选择一个元素,然后将该元素推入新的Array)。它们仅 differ ,其中Array用作“源”,而用作“目标”。这意味着您可以通过将“源”和“目标”数组作为参数/参数传递给函数

,轻松地从这两个函数创建单个函数:

function selectRandom (sourceArray, destinationArray) {
  var randomIndex = Math.floor(Math.random() * sourceArray.length);
  if (destinationArray.indexOf(sourceArray[randomIndex]) < 0) {
    destinationArray.push(sourceArray[randomIndex]);
  } else {
    selectRandom(sourceArray, destinationArray);
  }
}

这可以替换您当前拥有的两个功能(randNPrand)。您只需记住要传递正确的源数组和目标数组。

我们现在完成了吗?简而言之:不。我们可以进一步抽象该代码!让我们看一下两个循环

var CPselected = [];
for (var i = 0; i < 2; i++){
  rand();
}

// ... Left out for brevity ...

var NPselected = [];
for (var i = 0; i < 2; i++){
  NPrand();
}

猜猜是什么:它们的作用也完全相同,所以我们也将它们抽象掉。结合selectRandom函数,我们得出:

function randomSelect2 (sourceArray) {
  var destinationArray = [];
  for (var i = 0; i < 2; i += 1) {
    selectRandom(sourceArray, destinationArray);
  }
  return destinationArray;
}

签出:

function selectRandom (sourceArray, destinationArray) {
  var randomIndex = Math.floor(Math.random() * sourceArray.length);
  if (destinationArray.indexOf(sourceArray[randomIndex]) < 0) {
    destinationArray.push(sourceArray[randomIndex]);
  } else {
    selectRandom(sourceArray, destinationArray);
  }
}

function randomSelect2 (sourceArray) {
  var destinationArray = [];
  for (var i = 0; i < 2; i += 1) {
    selectRandom(sourceArray, destinationArray);
  }
  return destinationArray;
}



console.log(randomSelect2([1, 2, 3, 4, 5, 6]));
console.log(randomSelect2(['a', 'b', 'c', 'd']));

TL; DR

还不够吗?我们可以将现有的合并为一个函数。如果源数组中的随机元素已经存在于目标数组中,那么selectRandom函数已经使用了递归,对吗?通过传入另一个参数,该参数告诉我们要从源数组中选择的最大项目数,我们可以编写一个 recursive 函数,将所有内容包装到一个函数中

function randomSelect (count, sourceArray, destinationArray) {
  if (destinationArray.length >= count) {
    // the "base case", used to break out of recursion
    return destinationArray;
  }

  var randomIndex = Math.floor(Math.random() * sourceArray.length);
  var item = sourceArray[randomIndex];
  if (destinationArray.indexOf(item) < 0) {
    // call "randomSelect" again with the item added to the destination (recurse)
    return randomSelect(count, sourceArray, destinationArray.concat(item));
  }
  // call "randomSelect" again (recurse)
  return randomSelect(count, sourceArray, destinationArray);
}

console.log(randomSelect(2, [1, 2, 3, 4, 5], []));
console.log(randomSelect(2, ['a', 'b', 'c', 'd', 'e'], []));

太棒了。尽管有一个明显的缺点,但尚不明显:到目前为止,此函数并不安全堆栈,这意味着大量(第一个参数)可能会破坏堆栈 。要解决此问题,您可以使用蹦床。但是,没有必要使用递归定义。如果您想走到那个兔子洞,看看here

答案 2 :(得分:-2)

function randomSelect (count, sourceArray, destinationArray) {
  if (destinationArray.length >= count) {
    // the "base case", used to break out of recursion
    return destinationArray;
  }

  var randomIndex = Math.floor(Math.random() * sourceArray.length);
  var item = sourceArray[randomIndex];
  if (destinationArray.indexOf(item) < 0) {
    // call "randomSelect" again with the item added to the destination (recurse)
    return randomSelect(count, sourceArray, destinationArray.concat(item));
  }
  // call "randomSelect" again (recurse)
  return randomSelect(count, sourceArray, destinationArray);
}

console.log(randomSelect(2, [1, 2, 3, 4, 5], []));
console.log(randomSelect(2, ['a', 'b', 'c', 'd', 'e'], []));
感谢您提供详细的答案,但我认为它没有得到我所得到的,我将编写所有代码,以便可以看到。 在数组中,有5组25个项目。

var question = [
   CP = [
      { questionNumber: "1", type: "CP", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "2", type: "CP", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "3", type: "CP", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "4", type: "CP", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "5", type: "CP", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ],
    NP = [
      { questionNumber: "6", type: "NP", question: "quien es mas wapo?", answer1: "yo", answer2:"javier"},
      { questionNumber: "7", type: "NP", question: "te gusta viajar?", answer1: "si", answer2:"no"},
      { questionNumber: "8", type: "NP", question: "eres romantico?", answer1: "si", answer2:"a veces"},
      { questionNumber: "9", type: "NP", question: "que te gusta mas?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "10", type: "NP", question: "eres mas...", answer1: "dormilon", answer2:"hablador"}
   ],
   A = [
      { questionNumber: "11", type: "A", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "12", type: "A", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "13", type: "A", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "14", type: "A", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "15", type: "A", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ],
   FC = [
      { questionNumber: "16", type: "FC", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "17", type: "FC", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "18", type: "FC", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "19", type: "FC", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "20", type: "FC", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ],
   AC = [
      { questionNumber: "21", type: "AC", question: "paski?", answer1: "yo", answer2:"javier"},
      { questionNumber: "22", type: "AC", question: "pepino?", answer1: "si", answer2:"no"},
      { questionNumber: "23", type: "AC", question: "cabron?", answer1: "si", answer2:"a veces"},
      { questionNumber: "24", type: "AC", question: "ostia?", answer1: "carne", answer2:"pescado"},
      { questionNumber: "25", type: "AC", question: "adios.", answer1: "dormilon", answer2:"hablador"}
   ]
];

所以这里我有5倍的功能来从每个组中获取2个随机项。

var CPselected = [];
for (var i = 0; i < 2; i++){
    rand();
}
function rand(){
    var ran = CP[Math.floor(Math.random() * CP.length)];  
    if (CPselected.indexOf(ran) == -1)
        CPselected.push(ran);
    else
         rand();
}

var NPselected = [];
for (var i = 0; i < 2; i++){
    NPrand();
}
function NPrand(){
    var ran = NP[Math.floor(Math.random() * NP.length)];  
    if (NPselected.indexOf(ran) == -1)
        NPselected.push(ran);
    else
         NPrand();
}

var Aselected = [];
for (var i = 0; i < 2; i++){
    Arand();
}
function Arand(){
    var ran = A[Math.floor(Math.random() * A.length)];  
    if (Aselected.indexOf(ran) == -1)
        Aselected.push(ran);
    else
         Arand();
}

var FCselected = [];
for (var i = 0; i < 2; i++){
    FCrand();
}
function FCrand(){
    var ran = FC[Math.floor(Math.random() * FC.length)];  
    if (FCselected.indexOf(ran) == -1)
        FCselected.push(ran);
    else
         FCrand();
}

var ACselected = [];
for (var i = 0; i < 2; i++){
    ACrand();
}
function ACrand(){
    var ran = AC[Math.floor(Math.random() * AC.length)];  
    if (ACselected.indexOf(ran) == -1)
        ACselected.push(ran);
    else
         ACrand();
}

在这里我将5个数组合并为一个


var Selected = CPselected.concat(NPselected, Aselected, FCselected, ACselected);

在这里,我用html显示它

document.getElementById("data_area").innerHTML = 
"<div id='question_1' class='question_data'><div class='no'>" +CPselected[0].questionNumber+ "</div><div class='type'>" +CPselected[0].type+ "</div><div class='question'>" + CPselected[0].question + "</div><div class='answer_1'>" + CPselected[0].answer1 + "</div><div class='answer_2'>" + CPselected[0].answer2 + "</div></div><div id='question_2' class='question_data'><div class='no'>" +CPselected[1].questionNumber+ "</div><div class='type'>" +CPselected[1].type+ "</div><div class='question'>" + CPselected[1].question + "</div><div class='answer_1'>" + CPselected[1].answer1 + "</div><div class='answer_2'>" + CPselected[1].answer2 + "</div></div>";