简体   繁体   English

如何拆分特定格式的字符串并将其分配给c#中的变量?

[英]How to split the string of specific format and assign it to variable in c#?

I am very new to C# and would need some advice on how to approach the following problem.我对 C# 非常陌生,需要一些关于如何解决以下问题的建议。

I have the following.我有以下。

string input = "{1, 'hello', 1, 3}, {2, 'othello', 0, 2}"

There could be cases where there is just one {} or more in the input string.在某些情况下,输入字符串中只有一个{}或多个。

I want to be able to to split the input string on the two or more {} and create an instance of the class Data and add each of the new instances to a List<Data> mydatalist() .我希望能够在两个或多个{}上拆分输入字符串并创建 class Data 的实例并将每个新实例添加到List<Data> mydatalist()

I have the following declaration of the Data class.我有以下数据 class 的声明。 I am not sure on how to split the input string and create the Data class instance from it.我不确定如何拆分输入字符串并从中创建 Data class 实例。

public partial class Data
{
    private:
    int id;
    string desc;
    int state;
    int res;

    public:
    Data(int idval, string indesc, int instate, int inres)
    {
        id=idval; desc=indesc; state=instate; res=inres; 
    }
}

In the end, my List<Data> mydatalist() would contain two Data class objects with the respective fields declared accordingly.最后,我的List<Data> mydatalist()将包含两个Data class 对象,并相应地声明了相应的字段。

void CreateInstances(string result)
{
   var temp = result.Split(); // This gives me every index?
}

Any help wold be appreciated.任何帮助将不胜感激。

  • Use a regular-expression for the repeating { <number>, <string>, <number>, <number> } part.对重复的{ <number>, <string>, <number>, <number> }部分使用正则表达式。
  • I strongly recommend using an immutable POCO instead of a mutable type as your code does.我强烈建议您使用不可变的 POCO,而不是像您的代码那样使用可变类型。
  • You said you're new to C# but I don't know if you're new to regular-expressions and parsing in genreal, but the regular-expression "matches" your input text and allows the program to extract data from it.您说您是 C# 的新手,但我不知道您是否对正则表达式和体裁解析不熟悉,但正则表达式“匹配”您的输入文本并允许程序从中提取数据。 Think of it as a more powerful form of a wildcard or glob search "foo*.txt" you may have seen already.将其视为您可能已经见过的更强大的通配符或全局搜索"foo*.txt"形式。
    • (\d+) means "match decimal digits" (\d+)表示“匹配十进制数字”
    • \s* means "expect optional whitespace here" \s*表示“此处期望可选空格”
    • '(.*?)' means "read every character between two quotes as a single value" '(.*?)'表示“将两个引号之间的每个字符读取为单个值”
    • You can try it out online here: https://regex101.com/r/mesMGG/1您可以在这里在线试用: https://regex101.com/r/mesMGG/1
  • The Match.NextMatch() method and Match.Successful properties allows the same regex to be run multiple times over an input string. Match.NextMatch()方法和Match.Successful属性允许在输入字符串上多次运行相同的正则表达式。
  • The matched text are returned as String values in Match.Groups[] .匹配的文本在Match.Groups[]中作为String值返回。
    • Note that Match.Groups[0] is always the whole input string, which is why my code starts at index 1 instead of 0 .请注意, Match.Groups[0]始终是整个输入字符串,这就是我的代码从索引1而不是0开始的原因。
    • Because they're String values, you need to use Int32.Parse or Int32.TryParse to convert them to Int32 values.因为它们是String值,所以您需要使用Int32.ParseInt32.TryParse将它们转换为Int32值。

Like so:像这样:

class Data
{

    public Data( Int32 id, String description, Int32 state, Int32 res )
    {
        this.Id = id;
        this.Description = description;
        this.State = state;
        this.Res = res;
    }

    public Int32 Id { get; }
    public String Description { get; }
    public Int32 State { get; }
    public Int32 Res { get; }
}

public static List<Data> ParseData( String input )
{
    RegEx r = new Regex( @"\{\s*(\d+)\s*,\s*'(.*?)'\s*,\s*(\d+)\s*,\s*(\d+)\s*\}" );

    List<Data> list = new List<Data>();

    Match m = r.Match( input );
    while( m.Success )
    {
        Int32  id    = Int32.Parse( m.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture );
        String desc  = m.Groups[2].Value;
        Int32  state = Int32.Parse( m.Groups[3].Value, NumberStyles.Integer, CultureInfo.InvariantCulture );
        Int32  res   = Int32.Parse( m.Groups[4].Value, NumberStyles.Integer, CultureInfo.InvariantCulture );

        Data d = new Data( id, desc, state, res );
        list.Add( d );

        m = m.NextMatch();
    }

    return list;
}

Used like so:像这样使用:

List<Data> list = ParseData( "{1, 'hello', 1, 3}, {2, 'othello', 0, 2}" );

If you use Newtonsoft JSON.NET and change your input to JSON:如果您使用Newtonsoft JSON.NET并将输入更改为 JSON:

string dataString = "[{id: 1, desc: "hello", state: 1, res: 3}, {id: 2, desc: "othello", state: 0, res: 2}]"
var dataObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Data>(dataString );

This should help.这应该会有所帮助。

This deals with dest having spaces.这处理dest有空格。

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

(...)

public static void Main(string[] args)
{

    string input = "{1, 'Western Australia', 1, 3}, {2, 'othello', 0, 2}";
    var pattern = "{(.*?)}";
    var matches = Regex.Matches(input, pattern);

    var separated = matches
                .Select(m => m.Groups[1].ToString())
                .ToList();

    var os = new Program().CreateInstances(separated).ToList();
}

IEnumerable<Data> CreateInstances(IEnumerable<string> separated)
    => separated.Select(o =>
        {
            var parts = o.Split(',').Select(s => s.Trim()).ToList();
            return new Data(
                int.Parse(parts[0]),
                parts[1].Trim('\''),
                int.Parse(parts[2]),
                int.Parse(parts[3]));
        });

Test测试

Code代码

// I made fields public just to print the values
foreach(var o in os ) Console.WriteLine($"id={o.id}, desc={o.desc}, state={o.state}, res={o.res}");

Output Output

// .NETCoreApp,Version=v3.0
id=1, desc=Western Australia, state=1, res=3
id=2, desc=othello, state=0, res=2

Here's an example just doing standard string manipulation w/ a few assumptions about the standardization of your data strings.这是一个示例,它只是对数据字符串的标准化进行了一些标准的字符串操作。

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
class Program
{
    static void Main(string[] args)
    {            
        string input = "{1, 'hello', 1, 3}, {2, 'othello', 0, 2}";

        //get the first start open curly
        int start = input.IndexOf('{');

        List<Data> list = new List<Data>();
        while (start >= 0)
        {
            //find position of first close curly after our open curly
            var end = input.IndexOf('}', start);

            //get all values between curlys
            var setValues = input.Substring(start + 1, (end - 1) - start);

            //split them into array
            var split = setValues.Split(',');

            list.Add(new Data()
            {
                Id = Convert.ToInt32(split[0]),
                Desc = split[1],
                State = Convert.ToInt32(split[2]),
                Res = Convert.ToInt32(split[3])
            });

            //get next open curly based off of most recent closed curly position
            start = input.IndexOf('{', end);
        }
    }
}
    public class Data
    {
        public int Id { get; set; }
        public string Desc { get; set; }
        public int State { get; set; }
        public int Res { get; set; }
    }
}

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

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