Создание динамического группового пользователя

#dart

#dart

Вопрос:

Я хочу создать простое приложение с именем «Генератор групп пользователей», оно будет генерировать группу в зависимости от списка пользователей и общей группы, которую вы хотите создать. Например, у вас есть 20 человек из списка и вы хотите создать 10 групп из этого списка, приложение автоматически сгенерирует 10 групп, и в каждой группе будет по 2 человека. Вот как я это реализую.

 class Person {
  final int id;
  final String name;
  Person({this.id, this.name});
}

List<Person> listPerson = [
  Person(id: 1, name: 'Ani'),
  Person(id: 2, name: 'Budi'),
  Person(id: 3, name: 'Citra'),
  Person(id: 4, name: 'Doni'),
  Person(id: 5, name: 'Emilia'),
  Person(id: 6, name: 'Frasisco'),
  Person(id: 7, name: 'Goyu'),
  Person(id: 8, name: 'Hani'),
  Person(id: 9, name: 'Intan'),
  Person(id: 10, name: 'Jeri'),
  Person(id: 11, name: 'Karina'),
  Person(id: 12, name: 'Lemi'),
  Person(id: 13, name: 'Momo'),
  Person(id: 14, name: 'Nini'),
  Person(id: 15, name: 'Opi'),
  Person(id: 16, name: 'Parto'),
  Person(id: 17, name: 'Queen'),
  Person(id: 18, name: 'Risa'),
  Person(id: 19, name: 'Sisca'),
  Person(id: 20, name: 'Toni'),
//   Person(id: 21, name: 'Ucok'),
//   Person(id: 22, name: 'Vani'),
//   Person(id: 23, name: 'Wahyu'),
//   Person(id: 24, name: 'Xixi'),
];


Map<String, List<Person>> generateGroup(
  List<Person> values, {
  int generateTotalGroup = 1,
}) {
  
  var tempMap = <String, List<Person>>{};
  var tempPersonList = <Person>[];
  var totalPersonEveryGroup = 0.0;

  final totalPerson = values.length;
  values.shuffle();
  if (totalPerson % generateTotalGroup == 0) {
    totalPersonEveryGroup = values.length / generateTotalGroup;

    for (int i = 1; i <= generateTotalGroup; i  ) {
      var nameGroup = "Group $i";
      var selectedPerson = values
          .getRange(tempPersonList.length,
              tempPersonList.length   totalPersonEveryGroup.toInt())
          .toList();

      tempMap[nameGroup] = selectedPerson;

      tempPersonList = [...tempPersonList, ...selectedPerson];
    }
  } else {
    /// Question to StackOverflow    
  }

  return tempMap;
}

void main() {
  final result = generateGroup(listPerson, generateTotalGroup: 10);
  
  result.forEach((key,listPerson){
    
    listPerson.forEach((person){
      print('key $key || person ${person.name}');
    });
    
  });
}

  

Вывод

 key Group 1 || person Emilia
key Group 1 || person Nini
key Group 2 || person Citra
key Group 2 || person Hani
key Group 3 || person Frasisco
key Group 3 || person Queen
key Group 4 || person Goyu
key Group 4 || person Risa
key Group 5 || person Karina
key Group 5 || person Intan
key Group 6 || person Lemi
key Group 6 || person Ani
key Group 7 || person Parto
key Group 7 || person Doni
key Group 8 || person Budi
key Group 8 || person Toni
key Group 9 || person Momo
key Group 9 || person Jeri
key Group 10 || person Sisca
key Group 10 || person Opi
  

Если общее количество человек можно разделить на необходимое количество групп, это нормально (20 человек / 10 групп = по 2 человека в каждой группе), результат применения — это то, что я ожидал.Но проблема в том, что когда невозможно разделить, я не знаю, как с этим справиться.

Пример, общее количество человек = 24, а общая необходимая группа = 10, если я разделю, это приведет к 2,4. То, что я ожидал, если результат не может быть разделен, выглядит следующим образом :

Ожидание

 key Group 1 || person Ani
key Group 1 || person Budi
key Group 1 || person Citra
key Group 2 || person Doni
key Group 2 || person Emilia
key Group 2 || person Frasisco
key Group 3 || person Goyu
key Group 3 || person Hani
key Group 3 || person Intan
key Group 4 || person Jeri
key Group 4 || person Karina
key Group 4 || person Lemi
key Group 5 || person Momo
key Group 5 || person Nini
key Group 6 || person Opi
key Group 6 || person Parto
key Group 7 || person Queen
key Group 7 || person Risa
key Group 8 || person Sisca
key Group 8 || person Toni
key Group 9 || person Ucok
key Group 9 || person Vani
key Group 10 || person Wahyu
key Group 10 || person Xixi
  

Как я могу сделать, как указано выше, если общее количество человек не может быть разделено на общее количество нужных групп?

Спасибо

Ответ №1:

Попробуйте что-то подобное:

 class Person {
  final int id;
  final String name;
  Person({this.id, this.name});
}

List<Person> listPerson = [
  Person(id: 1, name: 'Ani'),
  Person(id: 2, name: 'Budi'),
  Person(id: 3, name: 'Citra'),
  Person(id: 4, name: 'Doni'),
  Person(id: 5, name: 'Emilia'),
  Person(id: 6, name: 'Frasisco'),
  Person(id: 7, name: 'Goyu'),
  Person(id: 8, name: 'Hani'),
  Person(id: 9, name: 'Intan'),
  Person(id: 10, name: 'Jeri'),
  Person(id: 11, name: 'Karina'),
  Person(id: 12, name: 'Lemi'),
  Person(id: 13, name: 'Momo'),
  Person(id: 14, name: 'Nini'),
  Person(id: 15, name: 'Opi'),
  Person(id: 16, name: 'Parto'),
  Person(id: 17, name: 'Queen'),
  Person(id: 18, name: 'Risa'),
  Person(id: 19, name: 'Sisca'),
  Person(id: 20, name: 'Toni'),
  Person(id: 21, name: 'Ucok'),
  Person(id: 22, name: 'Vani'),
  Person(id: 23, name: 'Wahyu'),
  Person(id: 24, name: 'Xixi'),
];


Map<String, List<Person>> generateGroup(
  List<Person> values, {
  int generateTotalGroup = 1,
}) {
  
  var tempMap = <String, List<Person>>{};
  var tempPersonList = <Person>[];
  var totalPersonEveryGroup = 0;

  final totalPerson = values.length;
  values.shuffle();
  var extra = totalPerson % generateTotalGroup;
  
  totalPersonEveryGroup = values.length ~/ generateTotalGroup;

  for (int i = 1; i <= generateTotalGroup; i  ) {
    var end = totalPersonEveryGroup;
    if (extra > 0) {
      extra--;
      end  ;
    }

    var nameGroup = "Group $i";
    var selectedPerson = values
      .getRange(tempPersonList.length,
                tempPersonList.length   end)
      .toList();

    tempMap[nameGroup] = selectedPerson;

    tempPersonList = [...tempPersonList, ...selectedPerson];
  }

  return tempMap;
}

void main() {
  final result = generateGroup(listPerson, generateTotalGroup: 10);
  
  result.forEach((key,listPerson){
    
    listPerson.forEach((person){
      print('key $key || person ${person.name}');
    });
    
  });
}
  

Комментарии:

1. не могли бы вы объяснить мне, что означает эта строка var end = totalPersonEveryGroup; if (extra > 0) {extra--; end ;} ? я немного запутался в этой строке

2. extra содержит количество элементов, которых недостаточно для заполнения всей группы. И нам нужно распределить эти элементы по первым группам на 1 элемент. Для этого мы ввели новую переменную end , потому что собираемся изменить ее на единицу для нескольких первых элементов (поэтому мы не меняем totalPersonEveryGroup время от времени). Когда мы потратили предмет, мы должны уменьшить количество дополнительных предметов ( extra-- ) и увеличить количество предметов в текущей группе ( end ). И мы делаем это до тех пор, пока у нас не появятся дополнительные элементы, вот почему у нас есть условие ( extra > 0 ) .

Ответ №2:

Самый простой способ распределить n элементов по k сегментам — циклический перебор.

 List<List<T>> distribute<T>(List<T> elements, int buckets) {
  var result = [for (var i = 0; i < buckets; i  ) <T>[]];
  for (var i = 0, b = 0; i < elements.length; i  ) {
    result[b].add(elements[i]);
    b = b   1;
    if (b == buckets) b = 0;
  }
  return resu<
}
  

Это не даст вам желаемых результатов, когда первые элементы хранятся вместе. Вместо этого он распределит первые элементы с подсчетом количества сегментов в каждый отдельный сегмент, затем добавит следующие элементы с подсчетом количества сегментов в те же сегменты и т.д.

Если вы хотите сохранить элементы вместе, я бы сделал что-то немного более сложное:

 List<List<T>> split<T>(List<T> elements, int buckets) {
  var n = elements.length;
  var min = n ~/ buckets;
  var remainder = n.remainder(buckets); // Number of buckets with one more element.
  var i = 0;
  return [
    for (var b = 0; b < buckets; b  ) [
      for (var j = 0; j < min; j  ) elements[i  ],
      if (--remainder >= 0) elements[i  ]
    ]
  ];
}