如何使用Javascript对动态数组中的项进行分组

时间:2017-08-25 15:46:36

标签: javascript jquery arrays

这是简单的Javascript问题。我有两个阵列水果和篮子。篮子总是排序。

var fruits = [''];
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];

我希望篮子的每个元素都这样分组。

Apple
I have Apple
I have Apple

Banana
I have Banana

Orange
I have Orange
I have Orange
I have Orange

代码     HTML

<div id="table"></div>

Code JS

var fruits = [''];
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];

for (var i = 0; i < basket.length; i++) { 
  var fruit = basket[i];

  for (var j = 0; j < fruits.length; j++) {
    if (fruit == fruits[j]) {
      // Existing fruit
      $("#table").append("I have " + fruit);
      break;
    } else {
      // New fruit
      $("#table").append("<h1>" + fruit + "</h1>");
      $("#table").append("I have " + fruit);
      fruits.push(fruit);
      break;
    }
}

此代码不起作用。它最终看起来像这样。我该如何解决?篮子内的水果可能不同,所以这应该是动态的。

Apple
I have Apple

Apple
I have Apple

Banana
I have Banana

Orange
I have Orange

Orange
I have Orange

Orange
I have Orange

9 个答案:

答案 0 :(得分:1)

您可以使用数组方法reduce()。 reduce方法是将函数应用于累加器和数组中的每个项目,因此其目的主要是将数组“减少”为单个对象。

var arr = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];
var groupedElements = arr.reduce(function(groups, item) {
    groups[item] = groups[item] || 0;
    groups[item]++;
    return groups;
  }, {});

console.log(groupedElements);
//is {Apple: 2, Banana: 1, Orange: 3}

打印出来应该单独处理。

答案 1 :(得分:0)

如果您的数组已排序,则可以轻松保存最后一个“groupName”,并在第一次遇到新组时将其打印出来。 如果在此之前没有对.sort进行排序。

var basket = ["Apple", "Apple", "Orange", "Orange", "Orange", "Banana"];

let lastGroup = '';
for (var i = 0; i < basket.length; i++) {
  var fruit = basket[i];

  if (lastGroup !== fruit) {
    lastGroup = fruit;
    $("#table").append("<h1>" + fruit + "</h1>");
  }
  $("#table").append("I have " + fruit + "\n");
}
div {
  white-space: pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table"></div>

答案 2 :(得分:0)

如果将fruits更改为保持计数的对象,则可以执行

&#13;
&#13;
var fruits = {};
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];

$.each(basket, (_,fruit) => fruit in fruits ? fruits[fruit]++ : fruits[fruit] = 1);
$.each(fruits, (k,v) => {
  $("#table").append("<h1>" + k + "</h1>");
  $.each(Array(v).fill(0), () => $("#table").append("<p>I have " + k + "</p>"));
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table"></div>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

怎么样,只需更改console.log行以附加你的html:

Question  -Tracks the question of the survey
QID PK

Answers - Tracks the available answers for a survey item
AID PK

QuestionAnswers  - Identifies which answers can be used on which questions
QUID  PK
AID   PK

Users  - identifies a person taking a survey
UID  PK

UserAnswers - Identifes the answers a user has selected for a survey and relates to both users and questionAnswers  thus limiting which answers can be used for a question but each row allows the user to select 1-M answers as needed.
UID  PK
QID  PK
AID  PK

答案 4 :(得分:0)

我认为解决问题的方法之一是从数组中创建一个对象。该对象可以将水果名称作为关键,水果数量作为值。

然后使用pip install python-dateutil -t lib 将结果附加到表

&#13;
&#13;
for..in
&#13;
var fruits = [''];
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];
var fruitObject = {}

basket.forEach(function(item) {
  if (fruitObject.hasOwnProperty(item)) {
    fruitObject[item] = fruitObject[item] + 1

  } else {
    fruitObject[item] = 1;

  }
})

for (var keys in fruitObject) {
  $("#table").append("<h1>" + keys + "</h1>");
  for (var i = 0; i < fruitObject[keys]; i++) {
    $("#table").append("I have " + keys + '<br/>');

  }


}
&#13;
&#13;
&#13;

答案 5 :(得分:0)

也许您需要使用if (fruits.indexOf(fruit) !== -1)而不是for-loop来检查数组中是否存在水果:

var fruits = [''];
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];

for (i in basket) { 
    var fruit = basket[i];
    if (fruits.indexOf(fruit) !== -1) {
        // Existing fruit
        $("#table").append("I have " + fruit);
    } else {
        // New fruit
        $("#table").append("<h1>" + fruit + "</h1>");
        $("#table").append("I have " + fruit);
        fruits.push(fruit);
    }
}

答案 6 :(得分:0)

您的代码出现问题:

进入内循环时会出现问题。该循环不会搜索它只是将数组fruits的第一个元素与fruit数组中的当前basket进行比较。由于breakif内的现有else语句,循环仅迭代第一个元素并终止。因此,循环是无用的,您的代码等同于:

for (var i = 0; i < basket.length; i++) { 
  var fruit = basket[i];

  var j = 0;
  if (fruit == fruits[j]) {
      $("#table").append("I have " + fruit);
  } else {
      $("#table").append("<h1>" + fruit + "</h1>");
      $("#table").append("I have " + fruit);
      fruits.push(fruit);
  }
}

由于fruits[0] === ''将对所有水果执行else语句,因为它们都是!= ''。如果您从fruits数组中删除空字符串,那么只有Apple会显示正确,因为BananaOrange都是!= "Apple"

如何修复代码:

在执行任何代码(fruitsif内的代码)之前,您必须遍历else数组以查看当前水果是否存在。或者您可以使用indexOf之类的搜索功能来简化代码。

建议的解决方案:

如果数组已排序,则只需使用while显示"I have ..." s,然后再附加下一个h1元素。

&#13;
&#13;
var basket = ["Apple", "Apple", "Banana", "Orange", "Orange", "Orange"];

for(var i = 0; i < basket.length; i--) {
  var fruit = basket[i];                                      // the current fruit
  $("#table").append("<h1>" + fruit + "</h1>");               // append a title element
  while(basket[i++] === fruit)                                // while the next fruits are the same:
    $("#table").append("<div>I have " + fruit + "</div>");    // append the "I have ..." text
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table"></div>
&#13;
&#13;
&#13;

注意 for循环递减i而不是递增它。这是因为while实际上负责增量,当遇到新的水果时,i应该返回一步(for循环为我们做的)。

答案 7 :(得分:0)

不要在循环中将标记附加到DOM(除非它是不可避免的)。首先构建整个标记,然后立即添加它

var basket = ["Orange", "Apple", "Orange", "Apple", "Banana", "Orange"];

//generate the markup first, ...
var markup = basket
  //don't mutate the original Array
  .slice().sort()
  //generate the markup for each item in the sorted basket
  .map(function(fruit, index, array) {
    //check wether it's a new group
    var title = (!index || fruit !== array[index - 1]) ?
      "<h1>" + fruit + "</h1>\n" :
      "";
    //just for fun
    var article = /^[aeiou]/i.test(fruit) ? "an" : "a";

    //return the whole markup for this row
    return title + "I have " + article + " " + fruit + "\n";
  })
  .join("")

//... then append the whole markup at once
$("#table").append(markup);
#table {
  white-space: pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table"></div>

或者计算每个水果出现的频率,然后根据它来构建行:

var basket = ["Orange", "Apple", "Orange", "Apple", "Banana", "Orange"];

var countFruits = Object.create(null);

basket.forEach(function(fruit) {
  if (fruit in countFruits) {
    countFruits[fruit]++;
  } else {
    countFruits[fruit] = 1;
  }
});

//generate the markup first, ...
var markup = Object.keys(countFruits).map(function(fruit) {
  var title = "<h1>" + fruit + "</h1>";
  var article = /^[aeiou]/i.test(fruit) ? "an" : "a";
  var row = "I have " + article + " " + fruit + "\n";
  return title + row.repeat(countFruits[fruit]);
}).join("");

//... then append the whole markup at once
$("#table").append(markup);
#table {
  white-space: pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="table"></div>

第二个示例按照第一次出现的顺序保存组。

答案 8 :(得分:0)

我在你的代码中看到了两个错误:

首先是:var fruits = [''];你创建了数组,其中第一个元素是一个空字符串。在循环for (var j = 0; j < fruits.length; j++)中,您总是将篮子中的水果与空字符串进行比较(并认为它是新的水果),然后从循环中断开。

当你休息时,篮下的下一个水果再次与空字符串进行比较(再次被认为是新的)。你永远不会比较来自篮子的水果与来自水果阵列的任何元素过去的索引0。

在索引0处你有空字符串。

如果您将var fruits = [''];更改为var fruits = [];,则无法再次使用,因为您正在显示水果的循环将永远无法运行。

无论如何,console.log是你的朋友。如果你把这行

console.log('fruit=' + fruit, 'j=' + j, 'fruits[j]=' + fruits[j]);
console.log('fruits=', fruits);

for (var j = 0; j < fruits.length; j++) {之后,一切都会清楚:

fruit=Apple j=0 fruits[j]=  
fruits= Array [ "" ]  
fruit=Apple j=0 fruits[j]=  
fruits= Array [ "", "Apple" ]  
fruit=Banana j=0 fruits[j]=  
fruits= Array [ "", "Apple", "Apple" ]  
fruit=Orange j=0 fruits[j]=  
fruits= Array [ "", "Apple", "Apple", "Banana" ]  
fruit=Orange j=0 fruits[j]=  
fruits= Array [ "", "Apple", "Apple", "Banana", "Orange" ]  
fruit=Orange j=0 fruits[j]=  
fruits= Array [ "", "Apple", "Apple", "Banana", "Orange", "Orange" ]

我不会发布正确的代码,因为许多其他人已经发布了工作版本。