C# 按索引/参数拆分的字符串?

C# 按索引/参数拆分的字符串?,c#,string,split,C#,String,Split,在编写自己的函数之前,我只是想检查.NET库中是否存在类似string.split(string input,params int[]index)的函数? 这个函数应该在我传递给它的索引上拆分字符串 编辑:我不应该添加string.join语句-这很混乱。您可以使用string实例方法 分割方法根据识别模式分割字符串。非常适合分解逗号分隔的列表等 但是你是对的,没有内置的字符串方法来实现你想要的 总是有正则表达式的 下面是一个可以扩展的示例: string text = "0123456789

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


编辑:我不应该添加string.join语句-这很混乱。

您可以使用
string
实例方法


分割方法根据识别模式分割字符串。非常适合分解逗号分隔的列表等


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

总是有正则表达式的

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

 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;
 }
string text=“0123456789ABCDEF”;
Match m=新的正则表达式(({7})({4})({5})。Match(text);
如果(m.成功)
{
var result=新字符串[m.Groups.Count-1];
对于(变量i=1;i
下面是一个封装上述逻辑的函数:

    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;            
    }
public static string[]SplitAt(此字符串文本,参数int[]索引)
{
var pattern=新的StringBuilder();
var lastIndex=0;
foreach(指数中的var指数)
{
AppendFormat((.{{{0}}})”,index-lastIndex;
lastIndex=指数;
}
模式。追加((.+)”;
var match=newregex(pattern.ToString()).match(text);
如果(!match.Success)
{
抛出新ArgumentException(“文本不能按给定索引拆分”);
}
var result=新字符串[match.Groups.Count-1];
对于(变量i=1;i
这篇文章写得相当快,但我相信它说明了我的观点,并向评论作者Michael强调了我的观点。

一个可能的解决方案:

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;
    }
}
公共静态类StringExtension
{
公共静态字符串[]拆分(此字符串源,参数int[]大小)
{
var length=size.Sum();
if(length>source.length)返回null;
var resultSize=大小。长度;
if(长度
所有其他答案似乎都太复杂了,所以我尝试了一下

using System.Linq;

public static class StringExtensions
{
    /// <summary>
    ///     Returns a string array that contains the substrings in this instance that are delimited by specified indexes.
    /// </summary>
    /// <param name="source">The original string.</param>
    /// <param name="index">An index that delimits the substrings in this string.</param>
    /// <returns>An array whose elements contain the substrings in this instance that are delimited by one or more indexes.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="index" /> is null.</exception>
    /// <exception cref="ArgumentOutOfRangeException">An <paramref name="index" /> is less than zero or greater than the length of this instance.</exception>
    public static string[] SplitAt(this string source, params int[] index)
    {
        index = index.Distinct().OrderBy(x => x).ToArray();
        string[] output = new string[index.Length + 1];
        int pos = 0;

        for (int i = 0; i < index.Length; pos = index[i++])
            output[i] = source.Substring(pos, index[i] - pos);

        output[index.Length] = source.Substring(pos);
        return output;
    }
}
使用System.Linq;
公共静态类扩展
{
/// 
///返回一个字符串数组,该数组包含此实例中由指定索引分隔的子字符串。
/// 
///原始字符串。
///分隔此字符串中的子字符串的索引。
///其元素包含此实例中由一个或多个索引分隔的子字符串的数组。
///是空的。
///小于零或大于此实例的长度。
公共静态字符串[]SplitAt(此字符串源,参数int[]索引)
{
index=index.Distinct().OrderBy(x=>x.ToArray();
字符串[]输出=新字符串[index.Length+1];
int pos=0;
for(int i=0;i
这并不能直接回答您的一般性问题,但在最常见的情况下(或者至少是我遇到这个问题时正在搜索答案的情况下),
索引是单个
int
,这种扩展方法比返回
字符串[]
数组更简洁,尤其是在C#7中

为了证明它的价值,我使用
string.Substring()
与创建两个
char[]
数组、调用
text.CopyTo()
并通过调用
new string(charArray)
返回两个字符串进行了对比。使用
string.Substring()

C#7语法

公共静态类StringExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInline)]
公共静态(字符串左,字符串右)拆分(此字符串文本,int索引)=>
(text.Substring(0,索引),text.Substring(索引));
}
公共静态类程序
{
公共静态void Main()
{
var(左,右)=“左-右”。拆分(4);
控制台。WriteLine(左);
控制台。WriteLine(右);
}
}
C#6语法

注意:在C#7之前的版本中使用
Tuple
并不会节省太多的详细信息,而且只返回
字符串[2]
数组实际上可能更简洁

公共静态类StringExtensions
{
//我会用这些方法中的一种,不管你选择哪一种,
//将其重命名为SplitAt()
[MethodImpl(MethodImplOptions.AggressiveInline)]
公共静态元组tupleSplit(此字符串文本,int索引)=>
创建(text.Substring(0,索引),text.Substring(索引));
[MethodImpl(MethodImplOptions.AggressiveInline)]
公共静态字符串[]ArraySplitAt(此字符串文本,int索引)=>
新字符串[]{text.Substring(0,索引),text.Substring(索引)};
}
公共静态类程序
{
公共静态void Main()
{
tuplestringstuple=“leftright”。tuplesplit(4);
WriteLine(“元组方法”);
控制台写入线(stringsTuple.Item1);
控制台写入线(stringsTuple.Item2);
Console.WriteLine();
Console.WriteLine(“数组方法”);
string[]stringsArray=“leftright”.ArraySplitAt(4);
控制台。WriteLin
using System.Linq;

public static class StringExtensions
{
    /// <summary>
    ///     Returns a string array that contains the substrings in this instance that are delimited by specified indexes.
    /// </summary>
    /// <param name="source">The original string.</param>
    /// <param name="index">An index that delimits the substrings in this string.</param>
    /// <returns>An array whose elements contain the substrings in this instance that are delimited by one or more indexes.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="index" /> is null.</exception>
    /// <exception cref="ArgumentOutOfRangeException">An <paramref name="index" /> is less than zero or greater than the length of this instance.</exception>
    public static string[] SplitAt(this string source, params int[] index)
    {
        index = index.Distinct().OrderBy(x => x).ToArray();
        string[] output = new string[index.Length + 1];
        int pos = 0;

        for (int i = 0; i < index.Length; pos = index[i++])
            output[i] = source.Substring(pos, index[i] - pos);

        output[index.Length] = source.Substring(pos);
        return output;
    }
}
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"
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;
}