使用递归连接不同数组中的元素

时间:2014-08-14 07:40:59

标签: c# recursion

如果我有两个数组

A:[A,B] 
B:[1,2,3]

如何创建像[A_1, A_2, A_3, B_1, B_2, B_3]

这样的字符串列表

阵列的数量不规则,可能还有3个

A:[A,B] 
B:[1,2,3]
C:[w,x,y,z]
D:[m,n]
E:[p,q,r]

我可以使用递归来解决它吗?

5 个答案:

答案 0 :(得分:0)

这是对n-ary维度的简单迭代 - 不需要递归,只需要存储索引的数组。

static void Iterate(int[] iterators, ArrayList[] arrays) {
  for (var j = iterators.Length - 1; j >= 0; j--) {
    iterators[j]++;
    if (iterators[j] == arrays[j].Count) {
      if (j == 0) {
        break;
      }
      iterators[j] = 0;
    } else {
      break;
    }
  }

}
static IList<string> Merge(ArrayList[] arrays) {
  List<string> result = new List<string>();
  int[] iterators = new int[arrays.Length];
  while (iterators[0] != arrays[0].Count) {
    var builder = new StringBuilder(20);
    for(var index = 0; index < arrays.Length; index++) {
      if (index > 0) {
        builder.Append("_");
      }
      builder.Append(arrays[index][iterators[index]]);
    }
    result.Add(builder.ToString());
    Iterate(iterators, arrays);
  }
  return result;
}

static void Main(string[] args) {
  var list1 = new ArrayList();
  var list2 = new ArrayList();
  var list3 = new ArrayList();

  list1.Add(1);
  list1.Add(2);
  list2.Add("a");
  list2.Add("b");
  list3.Add("x");
  list3.Add("y");
  list3.Add("z");

  var result = Merge(new[] { list1, list2, list3 });
}

答案 1 :(得分:0)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace arrconn {
    class Program {
        static string[] conn(params Array[] arrs) {
            if(arrs.Length == 0) return new string[0];
            if(arrs.Length == 1) {
                string[] result = new string[arrs[0].Length];
                for(int i = 0; i < result.Length; i++)
                    result[i] = arrs[0].GetValue(i).ToString();
                return result; }
            else {
                string[] result = new string[arrs[0].Length*arrs[1].Length];
                for(int i = 0; i < arrs[0].Length; i++)
                    for(int j = 0; j < arrs[1].Length; j++)
                        result[i*arrs[1].Length+j] = string.Format("{0}_{1}", arrs[0].GetValue(i), arrs[1].GetValue(j));
                if(arrs.Length == 2) return result;
                Array[] next = new Array[arrs.Length-1];
                next[0] = result; Array.Copy(arrs, 2, next, 1, next.Length-1);
                return conn(next);
            }
        }
        static void Main(string[] args) {
            foreach(string s in  conn(
                new string[] { "A", "B" },
                new int[] { 1, 2, 3 },
                new string[] { "x" },
                new string[] { "$", "%", "#" }))
                Console.WriteLine(s);
            Console.Read();
        }
    }
}

答案 2 :(得分:0)

因此,我们定义了一个函数Merge,它获取了stings列表的列表并将它们合并到你想要的可枚举字符串中

static void Main(string[] args)
{
    var a = new[] { "A", "B" };
    var b = new[] { "1", "2", "3" };
    var c = new[] { "x", "y", "z", "w" };

    var result = Merge(a, b, c);
    foreach (var r in result)
    {
        Console.WriteLine(r);
    }
}

public static IList<string> Merge(params IEnumerable<string>[] lists)
{
    return Merge((IEnumerable<IEnumerable<string>>) lists);
}

public static IList<string> Merge(IEnumerable<IEnumerable<string>> lists)
{
    var retval = new List<string>();
    var first = lists.FirstOrDefault();
    if (first != null)
    {
        var result = Merge(lists.Skip(1));
        if (result.Count > 0)
        {
            foreach (var x in first)
            {                
                retval.AddRange(result.Select(y => string.Format("{0}_{1}", x, y)));
            }
        }                
        else
        {
            retval.AddRange(first);
        }            
    }

    return retval;
}

如果您使用Lists作为输入

,我们也可以改善这一点
public static IList<string> Merge(params IList<string>[] lists)
{
    return Merge((IList<IList<string>>) lists);
}

public static IList<string> Merge(IList<IList<string>> lists, int offset = 0)
{
    if (offset >= lists.Count)
        return new List<string>();

    var current = lists[offset];
    if (offset + 1 == lists.Count) // last entry in lists
        return current;

    var retval = new List<string>();

    var merged = Merge(lists, offset + 1);
    foreach (var x in current)
    {
        retval.AddRange(merged.Select(y => string.Format("{0}_{1}", x, y)));
    }

    return retval;
}

答案 3 :(得分:0)

我猜您的输入是这样的:

var A = ["A","B"];
var B = [1,2,3];
var C = ["x","y","z","w"];

你想要获得的是:

var result = ["A_1_x", "A_1_y",...
    "A_2_x", "A_2_y",...
    "A_3_x", "A_3_y",...
    "B_1_x", "B_1_y",...
    ...
    ..., "B_3_z", "B_3_w"];

我们将使用IEnumerable,因为它将简化我们的工作并让我们访问yield关键字。 首先,让我们来处理我们只收集两个集合的情况:

IEnumerable<string> ConcatEnumerables(IEnumerable<object> first, IEnumerable<object> second)
{
    foreach (var x in first)
    {
        foreach (var y in second)
        {
            yield return x.ToString() + "_" + y.ToString();
        }
    }
}

然后我们可以递归地获取任意数量的集合:

IEnumerable<string> ConcatEnumerablesRec(IEnumerable<IEnumerable<object>> enums)
{            
    //base cases
    if(!enums.Any())
    {
        return Enumerable.Empty<string>();
    }
    if (enums.Count() == 1)
    {
        return enums.First().Select(o => o.ToString());
    }

    //recursively solve the problem
    return ConcatEnumerables(enums.First(), ConcatEnumerablesRec(enums.Skip(1));
}

现在你需要在结果上调用ToArray,如果你真的需要一个数组作为输出。

string[] Concatenator(params object[][] parameters)
{
    return ConcatEnumerablesRec(parameters).ToArray();
}

答案 4 :(得分:0)

这应该可以解决问题。请注意,输入序列不必是数组 - 它们可以是实现IEnumerable<>的任何类型。

另请注意,我们必须将值类型的序列置于<object>的序列中,以便它们可分配给IEnumerable<object>

以下是可编辑的控制台应用演示代码:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    internal static class Program
    {
        static void Main()
        {
            string[] a = {"A", "B", "C", "D"};
            var      b = Enumerable.Range(1, 3); // <-- See how it doesn't need to be an array.
            char[]   c = {'X', 'Y', 'Z'};
            double[] d = {-0.1, -0.2};

            var sequences = new [] { a, b.Cast<object>(), c.Cast<object>(), d.Cast<object>() };

            Console.WriteLine(string.Join("\n", Combine("", sequences)));
        }

        public static IEnumerable<string> Combine(string prefix, IEnumerable<IEnumerable<object>> sequences)
        {
            foreach (var item in sequences.First())
            {
                string current = (prefix == "") ? item.ToString() : prefix + "_" + item;
                var remaining = sequences.Skip(1);

                if (!remaining.Any())
                {
                    yield return current;
                }
                else
                {
                    foreach (var s in Combine(current, remaining))
                        yield return s;
                }
            }
        }
    }

}