In C#, best way to check if stringbuilder contains

2020-08-14 09:39发布

问题:

I have an existing StringBuilder object, the code appends some values and a delimiter to it.

I want to modify the code to add the logic that before appending the text, it will check if it already exists in the StringBuilder. If it does not, only then will it append the text, otherwise it is ignored.

What is the best way to do so? Do I need to change the object to string type? I need the best approach that will not hamper performance.

public static string BuildUniqueIDList(context RequestContext)
{
    string rtnvalue = string.Empty;
    try
    {
        StringBuilder strUIDList = new StringBuilder(100);
        for (int iCntr = 0; iCntr < RequestContext.accounts.Length; iCntr++)
        {
            if (iCntr > 0)
            {
                strUIDList.Append(",");
            }

            // need to do somthing like:
            // strUIDList.Contains(RequestContext.accounts[iCntr].uniqueid) then continue
            // otherwise append
            strUIDList.Append(RequestContext.accounts[iCntr].uniqueid);
        }
        rtnvalue = strUIDList.ToString();
    }
    catch (Exception e)
    {
        throw;
    }
    return rtnvalue;
}

I am not sure if having something like this will be efficient:

if (!strUIDList.ToString().Contains(RequestContext.accounts[iCntr].uniqueid.ToString()))

回答1:

Personally I would use:

return string.Join(",", RequestContext.accounts
                                      .Select(x => x.uniqueid)
                                      .Distinct());

No need to loop explicitly, manually use a StringBuilder etc... just express it all declaratively :)

(You'd need to call ToArray() at the end if you're not using .NET 4, which would obviously reduce the efficiency somewhat... but I doubt it'll become a bottleneck for your app.)

EDIT: Okay, for a non-LINQ solution... if the size is reasonably small I'd just for for:

// First create a list of unique elements
List<string> ids = new List<string>();
foreach (var account in RequestContext.accounts)
{
    string id = account.uniqueid;
    if (ids.Contains(id))
    {
        ids.Add(id);
    }
}

// Then convert it into a string.
// You could use string.Join(",", ids.ToArray()) here instead.
StringBuilder builder = new StringBuilder();
foreach (string id in ids)
{
    builder.Append(id);
    builder.Append(",");
}
if (builder.Length > 0)
{
    builder.Length--; // Chop off the trailing comma
}
return builder.ToString();

If you could have a large collection of strings, you might use Dictionary<string, string> as a sort of fake HashSet<string>.