C# 当字符串中的字符';它比你的起始指数小?

C# 当字符串中的字符';它比你的起始指数小?,c#,indexof,substring,C#,Indexof,Substring,根据我的问题,我想得到当前开始索引之前第一个逗号的索引。举一个数据示例,我有一个如下字符串: bobgreen;警察局长安迪·理查兹;屋宇署署长弗兰克威廉斯,;噢,詹姆斯·克拉克;PM 该字符串包含设置为[Persons Name]的元素;[Role],因此名称与角色之间用分隔(分号),每个元素用,(逗号)相互分隔 字符串中的元素可以是任意顺序,因此我的问题的原因是,我想为角色OW获取人员的姓名。我最初的想法是得到的索引;哦,,然后从那里开始工作。很明显,我可以从开始索引检查时向后循环字符串,查

根据我的问题,我想得到当前开始索引之前第一个逗号的索引。举一个数据示例,我有一个如下字符串:

bobgreen;警察局长安迪·理查兹;屋宇署署长弗兰克威廉斯,;噢,詹姆斯·克拉克;PM

该字符串包含设置为
[Persons Name]的元素;[Role]
,因此名称与角色之间用
分隔(分号),每个元素用
(逗号)相互分隔

字符串中的元素可以是任意顺序,因此我的问题的原因是,我想为角色
OW
获取人员的姓名。我最初的想法是得到
的索引;哦,
,然后从那里开始工作。很明显,我可以从开始索引检查时向后循环字符串,查看字符是否为逗号,但这似乎效率低下,那么有更好的方法实现这一点吗

编辑

为了澄清,我只想获取与角色OW关联的名称。此角色只能在字符串中出现一次。如果没有,那么我很高兴只得到第一次出现,我认为IndexOf(“;OW”)就可以了。我不需要其他角色或名称,只需要与OW关联的名称

此外,角色的长度将仅为2个字符。正如Matt Burland所指出的,如果它位于字符串的末尾,那么后面就不会有逗号。但是,我可以修改我的indexof,只搜索“OW”,因为角色只有2个字符长。

使用
String.Split(',')
将逗号上的字符串拆分为一个数组。然后创建一个自定义对象:

public RoledPerson{
    public string Person;
    public string Role;

    public RoledPerson(string input){
        string[] splitInput = input.Split(';');
        Person = splitInput[0];
        Role = splitInput[1];
    }
}
然后,您可以将字符串转换为可枚举项,如下所示:

var RoledPersons inputstring.Split(',').Select(string => new RoledPerson(string));
然后你就可以找到任何角色的人作为他的角色:

var RoledPersonsWithRole = RoledPersons.Where(roledperson => roledperson.Role == "OW");
正如马特·伯兰(Matt Burland)所说,你也可以使用
字典
。我将把如何解决这个问题留给你。但是,这不支持具有相同名称的多个键,因此,如果您多次使用相同的角色,这将不起作用

免责声明:此处可能有错误。

使用包含起始位置的过载:

string s = "Bob Green;PD,Andy Richards;BD,Frank Williams;OW,James Clack;PM";
int startRole = s.IndexOf(";OW");
int startName = s.LastIndexOf(',',startRole) + 1;  // start at the semicolon before the role
string name s.Substring(startName,(startRole-startName));
请注意,需要考虑一些边缘情况:

  • 所有角色是否都是两个字符(例如,是否存在
    OWX
    角色)
  • 如果
    OW
    角色是列表中的第一个角色,则其前面不会有逗号
  • 是否有多个
    OW
    角色?如果是这样,您可以使用
    while
    循环,只需在上一个角色字符串的末尾开始搜索

这是获取所有
OW
的基本方法,而不仅仅是第一个或最后一个。将
OW
输入到第二个函数

class stringSections
{
    private List<string> role = new List<string>();
    private List<string> name = new List<string>();

    public void Input(string input)
    {
        string temp = "";
        for(int i =0;i<input.Length;i++)
        {
            if(input[i]==';')
            {
                name.Add(temp);
                temp = "";
            } else if(input[i]==',')
            {
                role.Add(temp);
                temp = "";
            } else
            {
                temp += input[i];
            }
        }
    }

    public List<string> GetAll(string prole)
    {
         List<string> reterners = new List<string>();

         for(int i = 0; i < role.Count;i++)
        {
            if (role[i] == prole)
            {
                reterners.Add(name[i]);
            }
        }
         return reterners;
    }
}
class-stringSections
{
私有列表角色=新列表();
私有列表名称=新列表();
公共无效输入(字符串输入)
{
字符串temp=“”;

对于(int i=0;i正则表达式如何。这应该可以:

string role = "OW";
string str = "Bob Green;PD,Andy Richards;BD,Frank Williams;OW,James Clack;PM";
string pattern = "([^,]*);" + role;
var match = Regex.Match(str, pattern);
if (match.Success)
{
    Console.WriteLine(match.Groups[1].Value);
}

要处理@D Stanley提出的边缘案例:

    var s = "Bob Williams;OW,Bob Green;PD,Frank Williams;OW,Andy Richards;BD,James Clack;PM,Dave Williams;OW";
    var r = new Regex("(;OW,|^OW,|;OW$)");
    if (r.IsMatch(s)) 
    {
        foreach (Match m in r.Matches(s)) 
        {
            var rIdx = m.Index;
            var pIdx = s.LastIndexOf(",",rIdx);
            var person = s.Substring(pIdx + 1, rIdx - pIdx - 1);
            Console.WriteLine(person);
        }
    }
    else 
    {
        Console.WriteLine("Role not found");
    }

为了确保我的“解决方案”有效,我用以下代码编写了一个快速apsx web表单:

<asp:Content ID="Content3" ContentPlaceHolderID="PageContent" runat="server">
<asp:HiddenField ID="TestString" runat="server" Value="Bob Green;PD,Andy Richards;BD,Frank Williams;OW,James Clack;PM" />
<asp:Label ID="Label1" runat="server" Text="Find people in role"></asp:Label>
<asp:TextBox ID="RoleToFind" runat="server"></asp:TextBox><br /><br />
<asp:TextBox ID="Result" runat="server" Rows="10" TextMode="MultiLine" Width="294px"></asp:TextBox>
<asp:Button ID="SearchButton" runat="server" Text="Search" OnClick="SearchButton_Click" />
最后,在aspx页面后面的代码中,我添加了以下内容:

    public partial class teststack : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void SearchButton_Click(object sender, EventArgs e)
    {
        List<RolePerson> lrp = new List<RolePerson>();

        // Get the string from the hidden field
        string strData = this.TestString.Value;
        // split the string into an array each value in the array haveing name;role
        string[] strRecords = strData.Split(new Char[] {','});
        // process the array and add to the list
        foreach (string s in strRecords)
        {
            string[] strRecord = s.Split(new Char[] { ';' });
            lrp.Add(new RolePerson{
                Person = strRecord[0],
                Role = strRecord[1]
            });
        }
        // Find the person for the specified role
        FindPerson(lrp, this.RoleToFind.Text);
    }

    //Find the people for the specified role and add to the results textbox
    private void FindPerson(List<RolePerson> lrp, string strRole)
    {
        this.Result.Text = null;
        string strResults = string.Empty;
        foreach (RolePerson rp in lrp)
        {
            if (rp.Role == strRole)
                strResults = strResults + rp.Person + "\r\n";
        }
        this.Result.Text = strResults;
    }
}
public分部类teststack:System.Web.UI.Page
{
受保护的无效页面加载(对象发送方、事件参数e)
{
}
受保护的无效搜索按钮\u单击(对象发送者,事件参数e)
{
List lrp=新列表();
//从隐藏字段中获取字符串
string strData=this.TestString.Value;
//将字符串拆分为一个数组,数组中的每个值都有name;role
字符串[]strRecords=strData.Split(新字符[]{',});
//处理数组并添加到列表中
foreach(strRecords中的字符串s)
{
字符串[]strRecord=s.Split(新字符[]{';'});
lrp.Add(新角色扮演者){
Person=strRecord[0],
角色=strRecord[1]
});
}
//查找指定角色的人员
FindPerson(lrp,this.RoleToFind.Text);
}
//查找指定角色的人员并添加到结果文本框
私有void FindPerson(列表lrp、字符串strole)
{
this.Result.Text=null;
string strResults=string.Empty;
foreach(lrp中的角色扮演者rp)
{
if(rp.Role==strRole)
strResults=strResults+rp.Person+“\r\n”;
}
this.Result.Text=strResults;
}
}
结果是:

使用上述方法,您将能够找到多个角色相同的人,并允许用户指定该角色


FindPerson可以进一步开发,以使用Linq查询,这将在更大的字符串上更有效。

字符串。LastIndexOf
?角色是唯一的还是可以有多个相同的角色?但更好的方法可能是将字符串解析为一个集合(可能是
字典
键入角色),这样您就可以很容易地查找任何角色并找到相关人员。@sr28是的,确实如此-但您可以在起始位置传递“从这里开始,而不是从字符串的末尾开始”@ZoomVirus询问OP,而不是我。这似乎相当冗长,只是为了得到一个名称。而且,字符串可能很长,有很多角色,所以我会花很多时间分离对我没有用处的角色。+1因为我认为使用类型化对象而不搜索字符串(特别是如果需要多次搜索字符串)是更好的方法。但是,你的答案实际上并不包括找到扮演
OW
@sr28角色的人:你的问题缺少很多上下文,所以很难说。如果你只从字符串中查找一个结果,而且只查找一次,那么就需要快速而肮脏的字符串搜索(参见D Stanley的答案)很好。如果需要在字符串中搜索多个人,请将其转换为
    public partial class teststack : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void SearchButton_Click(object sender, EventArgs e)
    {
        List<RolePerson> lrp = new List<RolePerson>();

        // Get the string from the hidden field
        string strData = this.TestString.Value;
        // split the string into an array each value in the array haveing name;role
        string[] strRecords = strData.Split(new Char[] {','});
        // process the array and add to the list
        foreach (string s in strRecords)
        {
            string[] strRecord = s.Split(new Char[] { ';' });
            lrp.Add(new RolePerson{
                Person = strRecord[0],
                Role = strRecord[1]
            });
        }
        // Find the person for the specified role
        FindPerson(lrp, this.RoleToFind.Text);
    }

    //Find the people for the specified role and add to the results textbox
    private void FindPerson(List<RolePerson> lrp, string strRole)
    {
        this.Result.Text = null;
        string strResults = string.Empty;
        foreach (RolePerson rp in lrp)
        {
            if (rp.Role == strRole)
                strResults = strResults + rp.Person + "\r\n";
        }
        this.Result.Text = strResults;
    }
}