字符串由index / params分割?

时间:2011-08-22 14:11:24

标签: c# string split

在我编写自己的函数之前,只想检查.NET库中是否存在类似string.split(string input, params int[] indexes)的函数? 这个函数应该在我传递给它的索引上拆分字符串。

编辑:我不应该添加string.join句子 - 这很令人困惑。

8 个答案:

答案 0 :(得分:13)

您可以使用String实例方法Substring

string a = input.Substring(0, 10);
string b = input.Substring(10, 5);
string c = input.Substring(15, 3);

答案 1 :(得分:5)

所有其他答案似乎太复杂了,所以我采取了刺。

./program --some-option --verbose --file="./myfile.txt" > ./output.txt 2> ./debug.out

答案 2 :(得分:2)

Split方法根据识别模式划分字符串。完美打破逗号分隔列表等。

但你是对的,没有内置的字符串方法来实现你想要的。

答案 3 :(得分:1)

一种可能的解决方案:

public static class StringExtension
{
    public static string[] Split(this string source, params int[] sizes)
    {
        var length = sizes.Sum();
        if (length > source.Length) return null;

        var resultSize = sizes.Length;
        if (length < source.Length) resultSize++;

        var result = new string[resultSize];

        var start = 0;
        for (var i = 0; i < resultSize; i++)
        {
            if (i + 1 == resultSize)
            {
                result[i] = source.Substring(start);
                break;
            }

            result[i] = source.Substring(start, sizes[i]);
            start += sizes[i];
        }

        return result;
    }
}

答案 4 :(得分:0)

总是有正则表达式。

以下是一个可以扩展的示例:

 string text = "0123456789ABCDEF";
 Match m = new Regex("(.{7})(.{4})(.{5})").Match(text);
 if (m.Success)
 {
     var result = new string[m.Groups.Count - 1];
     for (var i = 1; i < m.Groups.Count; i++)
         result[i - 1] = m.Groups[i].Value;
 }

这是一个封装上述逻辑的函数:

    public static string[] SplitAt(this string text, params int[] indexes)
    {
        var pattern = new StringBuilder();
        var lastIndex = 0;
        foreach (var index in indexes)
        {
            pattern.AppendFormat("(.{{{0}}})", index - lastIndex);
            lastIndex = index;
        }
        pattern.Append("(.+)");

        var match = new Regex(pattern.ToString()).Match(text);
        if (! match.Success)
        {
            throw new ArgumentException("text cannot be split by given indexes");
        }

        var result = new string[match.Groups.Count - 1];
        for (var i = 1; i < match.Groups.Count; i++)
            result[i - 1] = match.Groups[i].Value;
        return result;            
    }

这写得相当快,但我相信这说明了我的观点并强调了我对评论作者迈克尔的观点。

答案 5 :(得分:0)

这不会直接回答您的概括性问题,但最有可能是最常见的情况(或至少在我遇到此问题时我正在寻找答案的情况) ),其中indexes是单个int,这种扩展方法比返回string[]数组要干净一些,尤其是在C#7中。

对于它的价值,我使用string.Substring()进行了基准测试,以创建两个char[]数组,调用text.CopyTo()并通过调用new string(charArray)返回两个字符串。使用string.Substring()的速度大约是以前的两倍。

C#7语法

jdoodle.com example

public static class StringExtensions
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static (string left, string right) SplitAt(this string text, int index) => 
        (text.Substring(0, index), text.Substring(index));
}

public static class Program
{
    public static void Main()
    {
        var (left, right) = "leftright".SplitAt(4);
        Console.WriteLine(left);
        Console.WriteLine(right);
    }
}

C#6语法

jdoodle.com example

注意:在C#7之前的版本中使用Tuple<string, string>不会在冗长的方式上节省很多,实际上返回一个string[2]数组可能更干净。

public static class StringExtensions
{
    // I'd use one or the other of these methods, and whichever one you choose, 
    // rename it to SplitAt()

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static Tuple<string, string> TupleSplitAt(this string text, int index) => 
        Tuple.Create<string, string>(text.Substring(0, index), text.Substring(index));

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static string[] ArraySplitAt(this string text, int index) => 
        new string[] { text.Substring(0, index), text.Substring(index) };
}

public static class Program
{
    public static void Main()
    {
        Tuple<string, string> stringsTuple = "leftright".TupleSplitAt(4);
        Console.WriteLine("Tuple method");
        Console.WriteLine(stringsTuple.Item1);
        Console.WriteLine(stringsTuple.Item2);

        Console.WriteLine();

        Console.WriteLine("Array method");
        string[] stringsArray = "leftright".ArraySplitAt(4);
        Console.WriteLine(stringsArray[0]);
        Console.WriteLine(stringsArray[1]);
    }
}

答案 6 :(得分:0)

public static IEnumerable<string> SplitAt(this string source, params int[] index)
{
    var indices = new[] { 0 }.Union(index).Union(new[] { source.Length });

    return indices
                .Zip(indices.Skip(1), (a, b) => (a, b))
                .Select(_ => source.Substring(_.a, _.b - _.a));
}

var s = "abcd";

s.SplitAt(); // "abcd"
s.SplitAt(0); // "abcd"
s.SplitAt(1); // "a", "bcd"
s.SplitAt(2); // "ab", "cd"
s.SplitAt(1, 2) // "a", "b", "cd"
s.SplitAt(3); // "abc", "d"

答案 7 :(得分:0)

以“ List ”作为返回的版本。

来电者

string iTextLine = "02121AAAARobert Louis StevensonXXXX"
int[] tempListIndex = new int[] {
    // 0 -  // 0number  (exclude first)
    5,      // 1user
    9,      // 2name
    31      // role
};  

// GET - words from indexes
List<string> tempWords = getListWordsFromLine(iTextLine, tempListIndex);

方法

/// <summary>
/// GET - split line in parts using index cuts
/// </summary>
/// <param name="iListIndex">Input List of indexes</param>
/// <param name="iTextLine">Input line to split</param>
public static List<string> getListWordsFromLine(string iTextLine, int[] iListIndex)
{
    // INIT
    List<string> retObj = new List<string>(); 
    int currStartPos = 0;
    // GET - clear index list from dupl. and sort it
    int[] tempListIndex = iListIndex.Distinct()
                                    .OrderBy(o => o)
                                    .ToArray();
    // CTRL
    if (tempListIndex.Length != iListIndex.Length)
    {
        // ERR
        throw new Exception("Input  iListIndex contains duplicate indexes");
    }


    for (int jj = 0; jj < tempListIndex.Length; ++jj)
    {
        try
        {
            // SET - line chunk
            retObj.Add(iTextLine.Substring(currStartPos,
                                           tempListIndex[jj] - currStartPos));
        }
        catch (Exception)
        {
            // SET - line is shorter than expected
            retObj.Add(string.Empty);                    
        }                
        // GET - update start position
        currStartPos = tempListIndex[jj];
    }
    // SET
    retObj.Add(iTextLine.Substring(currStartPos));  
    // RET
    return retObj;
}