如何分组分割范围?



我正在用Dart编写微服务。通过向worker传递命令参数来服务运行worker: "app.exe -a=1,2,3,4"如果currentlyActiveWorkers等于4。然后,工作可以拆分为几个工人,如:

first: "app.exe -a=1,2,3,4"

second: "app.exe -a=5,6,7,8"

third: "app.exe -a=9,10,11,12"

第四个:"app.exe -a=13,14,15,16" .

我写了下一个原型:

void main() {
  
  int maxWorkers = 16;
  int currentlyActiveWorkers = 2;
  genJobs() {
    int step = 1; 
    int sliceSize = (maxWorkers/currentlyActiveWorkers).round(); 
    var list = [for(var i=step; i<=maxWorkers; i+=1) i];
    for(int i in Iterable<int>.generate(currentlyActiveWorkers))
    {
      print(list.sublist(i * sliceSize, sliceSize * step));
      step++;
    }
  }
  genJobs();
  
}

如果currentlyActiveWorkers是2的倍数,它可以正常工作。生成合适的工作数字:

[1, 2, 3, 4, 5, 6, 7, 8]
[9, 10, 11, 12, 13, 14, 15, 16]

但是如果用户指定例如3,则存在错误。最后一个号码是16。输出:

[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
[11, 12, 13, 14, 15]

对我来说没有关系,每组中+- 1的number元素对我来说是ok的。

您的舍入逻辑是不明确的。此外,您应该以不同的方式处理最后一块数据:

void main() {
  print(genJobs());
}
Map<int, List<int>> genJobs() {
  final activeWorkers = 3;
  final maxJobs = 16;
  final jobs = List<int>.generate(maxJobs, (i) => i + 1);
  final workerCapacity = (jobs.length / activeWorkers).floor();
  var chunks = <int, List<int>>{};
  for (var workerNumber = 0; workerNumber < activeWorkers; workerNumber++) {
    final startIndex = workerNumber * workerCapacity;
    final endIndex = startIndex + workerCapacity;
    final chunk = jobs.sublist(
      startIndex,
      endIndex > jobs.length || workerNumber == activeWorkers - 1
          ? jobs.length
          : endIndex,
    );
    chunks.addAll({workerNumber: chunk});
  }
  return chunks;
}

您的问题是,您首先为片选择了固定大小,即使元素的数量不是片计数的倍数。您很幸运,它是向下舍入而不是向上舍入,否则您会得到索引超出范围的错误(尝试包含17个元素和3组的代码)。

首先你应该弄清楚你想要什么结果。然后你可以试着编码。

对于22个元素和4个组,你可能需要两组6个元素和两组5个元素,而不是三组6个元素和一组4个元素(因为你说+/-1是可以的,而不是+/- 2)。

我会这样做:

/// Emits the integers from 0 to [elementCount] - 1 in [groupCount] grups.
///
/// The [elementCount] must be greater than zero.
/// The [groupCount] must be in the range 1..[elementCount],
/// meaning that each group will have at least one element, and 
/// each element is in at least one group.
Iterable<List<int>> evenlySpreadGroups(int elementCount, int groupCount) sync* {
  if (elementCount < 1) {
    throw RangeError.range(elementCount, 1, null, "elementCount");
  }
  RangeError.checkValueInInterval(groupCount, 1, elementCount, "groupCount");
  var list = <int>[];
  var groupIndex = 1;
  for (var i = 0; i < elementCount; i++) {
    while (i * groupCount >= groupIndex * elementCount) {
      yield list;
      list = [];
      groupIndex += 1;
    }
    list.add(i);
  }   
  yield list;
}

(如果您允许更多的组而不是元素,它也可以工作,任何groupCount>= 1,您将在输出中得到空列表,这很少有用)。

解决方案越多越好:

import 'package:lists/lists.dart';
void main() {
  final maxPartSize1 = 5;
  final data1 = genData(1, 16);
  print('data: $data1');
  final parts1 = split(data1, maxPartSize1);
  print('parts by $maxPartSize1: $parts1');
  print('=====');
  final maxPartSize2 = 3;
  final data2 = genData(2, 8);
  print('data: $data2');
  final parts2 = split(data2, maxPartSize2);
  print('parts by $maxPartSize2: $parts2');
}
List<int> genData(int start, int length) {
  return List<int>.generate(length, (i) => i + start);
}
Iterable<List<int>> split(List<int> data, int step) sync* {
  final length = data.length;
  for (final i in StepList(0, length - 1, step)) {
    var i2 = i + step;
    if (i2 > length) {
      i2 = length;
    }
    yield data.sublist(i, i2);
  }
}

输出:

data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
parts by 5: ([1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16])
=====
data: [2, 3, 4, 5, 6, 7, 8, 9]
parts by 3: ([2, 3, 4], [5, 6, 7], [8, 9])

的另一种方法:

void main() {
  final maxWorkers1 = 8;
  final datLen1 = 16;
  final data1 = [1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16];
  print('data: $data1');
  final parts1 = split(data1, maxWorkers1);
  print('$maxWorkers1 workers: $parts1');
  print('=====');
  final maxWorkers2 = 4;
  final datLen2 = 11;
  final data2 = genData(3, datLen2);
  print('data: $data2');
  final parts2 = split(data2, maxWorkers2);
  print('$maxWorkers2 workers: $parts2');
  print('=====');
  final maxWorkers3 = 8;
  final data3 = [7, 8, 3, 4];
  print('data: $data3');
  final parts3 = split(data3, maxWorkers3);
  print('$maxWorkers3 workers: $parts3');
}
List<int> genData(int start, int length) {
  return List<int>.generate(length, (i) => i + start);
}
Iterable<List<int>> split(List<int> data, int divider) sync* {
  if (divider <= 0) {
    throw RangeError.value(divider, 'divider', 'Must be greater than 0');
  }
  if (data.isEmpty) {
    // Nothing to do
    return;
  }
  final length = data.length;
  divider = divider > length ? length : divider;
  var partSize = length ~/ divider;
  if (length != partSize * divider) {
    partSize++;
  }
  for (var i = 0; i < divider; i++) {
    final start = i * partSize;
    if (start >= length) {
      break;
    }
    var end = start + partSize;
    if (end > length) {
      end = length;
    }
    yield data.sublist(start, end);
  }
}
输出:

data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
3 workers: ([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16])
=====
data: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
4 workers: ([3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13])
=====
data: [7, 8, 3, 4]
8 workers: ([7], [8], [3], [4])

最新更新