我要解决的问题如下:
我有一个$version=Online
"#% impex.setTargetFile( ""Product.csv"" );"
insert_update Product ; catalog(id [allownull=true] ; catalogVersion(catalog(id),version)[unique=true,allownull=true] ; code[unique=true,allownull=true] ; name
"#% impex.exportItems(""SELECT {P:pk} FROM {Product as P}, {CatalogVersion as CV}, {Catalog as C} WHERE {P:catalogversion}={CV:PK} AND {CV:catalog}={C:PK} AND {C:id}='$catalog' AND {CV:version}='$version'"", Collections.EMPTY_MAP, Collections.singletonList( Item.class ), true, true, -1, -1 );"
,我们称之为“ List<string>
”。
我需要与该列表中的所有字符串进行交互,因此我必须对其进行枚举。但是,问题来了,每次我互动时,我都必须取其中的“ x”个元素。
initialList
是x
,因此每次都是随机的。
这是我想要做的一个真实的例子:
假设列表new Random().Next(_minValue, _maxValue);
包含以下元素:
initialList
。
我想遍历所有元素,一次获取2-3个字符串,并用组合的元素保存一个新字符串。
因此,一种可能的输出(随随机返回的值而异)是:
test, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11, test12
我想做什么:
{ "test", "test1", "test2" },
{ "test3", "test4" },
{ "test5", "test6" },
{ "test7", "test8" },
{ "test9", "test10", "test11" },
{ "test12" }
我一直在思考,但是如果我在循环之外生成随机数,那么它将始终是相同的。我希望每次的字符串数量都是随机的。
此外,想到通过选择带有索引的元素来进行LINQ,但是不知道如何从那里继续。
感谢您的帮助。
答案 0 :(得分:3)
希望这会给您一个想法。
var mergedList = new List<string>();
for(int i = 0; i < initialList.Count; ){
var n = _random.Next(2,4);
mergedList.Add(initialList.Skip(i).Take(n).Aggregate((x,y) => x + y));
i += n;
}
答案 1 :(得分:2)
我认为最好的解决方案是使用LINQ Skip
跳过您已经处理过的元素,并使用Take
提取随机数量的元素。
const int _minValue = 2;
const int _maxValue = 4; // note max of random is exclusive, so this config takes 2 or 3 elements
var _random = new Random(Guid.NewGuid().GetHashCode());
List<string> initialList = new List<string>{"test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12"};
var currentPosition = 0;
while (currentPosition < initialList.Count()) {
var toTake = _random.Next(_minValue, _maxValue);
var mergedString = string.Join(", ", initialList.Skip(currentPosition).Take(toTake));
currentPosition += toTake;
}
请注意,此代码可能导致最后一个mergedString
仅包含一个元素(最后一个)。
工作示例:C# Fiddle。
答案 2 :(得分:2)
您可以尝试直接GroupBy
:
List<string> initialList = Enumerable
.Range(1, 15)
.Select(i => $"test{i}")
.ToList();
int _minMentions = 2;
int _maxMentions = 3;
// Random(1): to make outcome reproducible
// In real life should be new Random();
Random _random = new Random(1);
int group = 0;
int groupLength = 0;
var result = initialList
.Select((item) => {
if (--groupLength <= 0) {
group += 1;
groupLength = _random.Next(_minMentions, _maxMentions + 1);
}
return new { item, group };
})
.GroupBy(item => item.group)
.Select(chunk => chunk
.Select(item => item.item)
.ToList())
.ToList();
string test = string.Join(Environment.NewLine, result
.Select(items => string.Join(", ", items)));
Console.Write(test);
结果:
test1, test2
test3, test4
test5, test6
test7, test8, test9
test10, test11, test12
test13, test14
test15
答案 3 :(得分:1)
您可以使用IEnumerable.Skip和Take循环遍历初始列表,并创建所需大小的块,直到需要处理的元素为止。
List<string> initiallist = new List<string>
{"test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12"};
// We store the results here
List<List<string>> result = new List<List<string>>();
Random rnd = new Random();
int pos = 0;
while (pos < initiallist.Count())
{
// Define a block size of 2/3 elements
int block = rnd.Next(2,4);
// Extract the block size from the previous position
List<string> temp = initiallist.Skip(pos).Take(block).ToList();
// Add the sublist to our results
result.Add(temp);
// Point to the beginning of the next block
pos += block;
}
答案 4 :(得分:1)
使用Linq可以实现以下目的:
var initialList = new[]
{
"test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11",
"test12"
};
var newLists = new List<IEnumerable<string>>();
var rnd = new Random();
int minMentions = 2;
int maxMentions = 3;
int c = 0;
while (c < initialList.Length)
{
int elementsToTake = rnd.Next(minMentions, maxMentions + 1);
newLists.Add(initialList.Skip(c).Take(elementsToTake));
c += elementsToTake;
}
(随机)导致的结果:
{ test, test2, test3 }
{ test4, test5 }
{ test6, test7, test8 }
{ test9, test10, test11 }
{ test12 }
请注意,Take
仅接受可用物品,因此您不必担心elementsToTake
的体积要大于initialList
的体积。
答案 5 :(得分:0)
我知道有很多不错的答案,但是如果您喜欢IEnumerable,就可以尝试一下
public static class EnumerableGroupOf
{
public static IEnumerable<IEnumerable<TSource>> RandomGroupOf<TSource>(this IEnumerable<TSource> source, int[] groupLengths)
{
Random random = new Random();
var itemsLeft = source;
while (itemsLeft.Any())
{
var count = groupLengths[random.Next(0, groupLengths.Length)];
var items = itemsLeft.Take(count);
itemsLeft = itemsLeft.Skip(count);
yield return items;
}
}
}
这不会跳过而只处理铰孔的所有项目,因此使用Enumerable可能会更好。