我正在用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])