Eric Lippert's challenge “comma-quibbling”, best answer?

后端 未结 27 2247
日久生厌
日久生厌 2020-12-01 06:59

I wanted to bring this challenge to the attention of the stackoverflow community. The original problem and answers are here. BTW, if you did not follow it before, you should

27条回答
  •  生来不讨喜
    2020-12-01 07:09

    This isn't brilliantly readable, but it scales well up to tens of millions of strings. I'm developing on an old Pentium 4 workstation and it does 1,000,000 strings of average length 8 in about 350ms.

    public static string CreateLippertString(IEnumerable strings)
    {
        char[] combinedString;
        char[] commaSeparator = new char[] { ',', ' ' };
        char[] andSeparator = new char[] { ' ', 'A', 'N', 'D', ' ' };
    
        int totalLength = 2;  //'{' and '}'
        int numEntries = 0;
        int currentEntry = 0;
        int currentPosition = 0;
        int secondToLast;
        int last;
        int commaLength= commaSeparator.Length;
        int andLength = andSeparator.Length;
        int cbComma = commaLength * sizeof(char);
        int cbAnd = andLength * sizeof(char);
    
        //calculate the sum of the lengths of the strings
        foreach (string s in strings)
        {
            totalLength += s.Length;
            ++numEntries;
        }
    
        //add to the total length the length of the constant characters
        if (numEntries >= 2)
            totalLength += 5;  // " AND "
    
        if (numEntries > 2)
            totalLength += (2 * (numEntries - 2)); // ", " between items
    
        //setup some meta-variables to help later
        secondToLast = numEntries - 2;
        last = numEntries - 1;
    
        //allocate the memory for the combined string
        combinedString = new char[totalLength];
        //set the first character to {
        combinedString[0] = '{';
        currentPosition = 1;
    
        if (numEntries > 0)
        {
            //now copy each string into its place
            foreach (string s in strings)
            {
                Buffer.BlockCopy(s.ToCharArray(), 0, combinedString, currentPosition * sizeof(char), s.Length * sizeof(char));
                currentPosition += s.Length;
    
                if (currentEntry == secondToLast)
                {
                    Buffer.BlockCopy(andSeparator, 0, combinedString, currentPosition * sizeof(char), cbAnd);
                    currentPosition += andLength;
                }
                else if (currentEntry == last)
                {
                    combinedString[currentPosition] = '}'; //set the last character to '}'
                    break;  //don't bother making that last call to the enumerator
                }
                else if (currentEntry < secondToLast)
                {
                    Buffer.BlockCopy(commaSeparator, 0, combinedString, currentPosition * sizeof(char), cbComma);
                    currentPosition += commaLength;
                }
    
                ++currentEntry;
            }
        }
        else
        {
            //set the last character to '}'
            combinedString[1] = '}';
        }
    
        return new string(combinedString);
    }
    

提交回复
热议问题