通过子阵列拆分数组

时间:2012-01-24 23:27:46

标签: c# arrays

我有一个数组,例如

char[] myArr = {'a', 'b', '1', '2', 'c', 'd', '1', '2', 'e', 'f'}

在这种情况下,分隔子序列是{'1','2'}。

我希望按此序列拆分数组,并在结果中包含数组列表:

{'a', 'b'}
{'c', 'd'}
{'e', 'f'}

最快的方法是什么?

4 个答案:

答案 0 :(得分:2)

new string(myArr)
    .Split(new[] { "12" }, StringSplitOptions.None)
    .Select(s => s.ToCharArray())
        .ToList();

或者,如果您在说“list”时表示“数组”,那么

new string(myArr)
    .Split(new[] { "12" }, StringSplitOptions.None)
    .Select(s => s.ToCharArray())
        .ToArray();

此外,您可能更喜欢StringSplitOptions.RemoveEmptyEntries

如果这是作业,那么这个解决方案可能是不可接受的。


当你询问处理字节时,这里有一个适应性用途。首先,将字节数组转换为字符串并返回的几种方法:

string ByteArrayToString(byte[] arr)
{
    char[] charArray = arr.Select(b => (char)b).ToArray();
    return new string(charArray);
}

byte[] StringToByteArray(string s)
{
    //this method maps each char in the string to a single output byte;
    //all chars should be in the range 0 to 255.  The checked 
    //conversion will catch any data that violates this requirement.

    return s.Select(c => checked ( (byte)c )).ToArray();
}

现在,示例代码片段:

byte[] myArr = Whatever();
byte[] myDelim = WhateverElse();

string sourceData = ByteArrayToString(myArr);
string delimiter = ByteArrayToString(myDelim);

string[] splitData = sourceData.Split(new [] { delimiter }, StringSplitOptions.None);
byte[][] result = splitData.Select(StringToByteArray);

答案 1 :(得分:1)

我首先使用ForEach loopChar.IsLetter function。向我们展示一些代码,我们会帮助您。

答案 2 :(得分:1)

由于您正在处理字符,因此可以将myArr数组转换为字符串,并使用C#的String.Split方法。结果将是一个字符串数组,您可以在完成后将它们分成单个字符,这是一个示例:

  char[] myArr = {'a', 'b', '1', '2', 'c', 'd', '1', '2', 'e', 'f'};
  var myArrFlattened = "";
  myArr.ToList().ForEach(c => myArrFlattened += c.ToString());
  var separators = new string[] {"12"}; // put your sequences of characters here as a string
  myArrFlattened.Split(separators, StringSplitOptions.None);

最后一行的值是这个数组:{"ab", "cd", "ef"},此代码不会将字符串拆分为字符列表,为此,您可以使用foreach并应用{{1功能。

答案 3 :(得分:1)

string s = new String(myArr);
string[] parts = s.Split(new string[] {"12"}, StringSplitOptions.None);

然后,您可以使用

将结果转换为char数组
var list = new List<char[]>();
foreach (string part in parts) {
    list.Add(part.ToCharArray());
}

编辑:由于您需要通用方法,这里有两个通用解决方案。

如果子阵列的长度始终相同,那么你可以这样做:

public List<T[]> GetSubArrays<T>(T[] array)
{
    const int LengthOfSpearator = 2, LengthOfSubArray = 2;
    const int LengthOfPattern = LengthOfSpearator + LengthOfSubArray;

    var list = new List<T[]>();
    for (int i = 0; i <= array.Length - LengthOfSubArray; i += LengthOfPattern) {
        T[] subarray = new T[LengthOfSubArray];
        Array.Copy(array, i, subarray, 0, LengthOfSubArray);
        list.Add(subarray);
    }
    return list;
}

如果子阵列的长度是可变的,则算法变得更加复杂。我们还必须将泛型参数约束为IEquatable,以便能够进行比较。

public List<T[]> GetSubArrays<T>(T[] array, T[] separator)
    where T : IEquatable<T>
{
    int maxSepIndex = array.Length - separator.Length;
    var list = new List<T[]>();
    for (int i = 0; i <= array.Length; ) {
        // Get index of next separator or array.Length if none is found
        int sepIndex;
        for (sepIndex = i; sepIndex <= maxSepIndex; sepIndex++) {
            int k;
            for (k = 0; k < separator.Length; k++) {
                if (!array[sepIndex + k].Equals(separator[k])) {
                    break;
                }
            }
            if (k == separator.Length) { // Separator found at sepIndex
                break;
            }
        }
        if (sepIndex > maxSepIndex) { // No separator found, subarray goes until end.
            sepIndex = array.Length;
        }

        int lenSubarray = sepIndex - i;
        T[] subarray = new T[lenSubarray];
        Array.Copy(array, i, subarray, 0, lenSubarray);
        list.Add(subarray);
        i = sepIndex + separator.Length;
    }
    return list;
}