简体   繁体   English

动态for循环遍历列表(C#)

[英]Dynamic for loops over lists (C#)

I have 3 lists, containing strings 我有3个列表,其中包含字符串

  GenderList = ["M", "F"] 
  AgeList    = ["10-15", "16-20", "21-26"]
  CityList   = ["CityA", "CityB"]

I want to make cross product over the lists, but danamically: if the user asks for gender_city : I need the following: 我想在列表上做交叉乘积,但是很麻烦:如果用户要求gender_city :我需要以下内容:

 foreach(var g in GenderList)
    foreach(var c in CityList
     .....

If the user asks for gender_city_age , the loop must be: 如果用户要求输入gender_city_age ,则循环必须为:

foreach(var g in GenderList)
  foreach(var c in CityList)
    foreach(var a in AgeList)
       ....

if the user asks for city_age 用户是否要求city_age

foreach(var c in CityList)
   foreach(var a in AgeList)
      ...

How can I make this? 我该怎么做? I have about 20 lists, I need to multiply lists' items dynamically thanks 我大约有20清单,我需要动态地增加清单中的项目,谢谢

Let's start from generalized Cartesian : 让我们从广义Cartesian开始:

private static IEnumerable<T[]> Cartesian<T>(IEnumerable<IEnumerable<T>> source) {
  T[][] lists = source
    .Select(line => line.ToArray())
    .ToArray();

  if (source.Any(line => !line.Any()))
    yield break;

  int[] indexes = new int[lists.Length];

  do {
    yield return lists.Select((line, index) => line[indexes[index]]).ToArray();

    for (int i = 0; i < indexes.Length; ++i)
      if (++indexes[i] < lists[i].Length) 
        break;
      else
        indexes[i] = 0;
  }
  while (!indexes.All(index => index == 0));
}

Then we can try using it. 然后,我们可以尝试使用它。 Let's organize all the collections we want to query into a single dictionary : 让我们将要查询的所有集合组织到一个字典中

// we allow to use any IEnumerable<string>, not necessary List<string>
Dictionary<string, IEnumerable<string>> data = 
  new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase) {
    { "Gender", new [] { "M", "F" } },
    { "Age",    new List<string> { "10-15", "16-20", "21-26" } },
    { "City",   new [] { "CityA", "CityB" } },
};

And query it: 并查询:

 string userChoice = "gender_city_age";

 var result = Cartesian(userChoice.Split('_').Select(name => data[name]));

 // Have a look at the result:
 string report = string.Join(Environment.NewLine, result
   .Select(line => string.Join(", ", line)));

 Console.Write(report);

Outcome: 结果:

M, CityA, 10-15
F, CityA, 10-15
M, CityB, 10-15
F, CityB, 10-15
M, CityA, 16-20
F, CityA, 16-20
M, CityB, 16-20
F, CityB, 16-20
M, CityA, 21-26
F, CityA, 21-26
M, CityB, 21-26
F, CityB, 21-26

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM