How to split string preserving whole words?

前端 未结 10 2265
梦谈多话
梦谈多话 2020-11-30 09:18

I need to split long sentence into parts preserving whole words. Each part should have given maximum number of characters (including space, dots etc.). For example:

相关标签:
10条回答
  • 2020-11-30 09:51

    I've been testing Jon's and Lessan's answers, but they don't work properly if your max length needs to be absolute, rather than approximate. As their counter increments, it doesn't count the empty space left at the end of a line.

    Running their code against the OP's example, you get:

    1 part: "Silver badges are awarded for " - 29 Characters
    2 part: "longer term goals. Silver badges are" - 36 Characters
    3 part: "uncommon. " - 13 Characters
    

    The "are" on line two, should be on line three. This happens because the counter does not include the 6 characters from the end of line one.

    I came up with the following modification of Lessan's answer to account for this:

    public static class ExtensionMethods
    {
        public static string[] Wrap(this string text, int max)
        {
            var charCount = 0;
            var lines = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            return lines.GroupBy(w => (charCount += (((charCount % max) + w.Length + 1 >= max) 
                            ? max - (charCount % max) : 0) + w.Length + 1) / max)
                        .Select(g => string.Join(" ", g.ToArray()))
                        .ToArray();
        }
    }
    
    0 讨论(0)
  • 2020-11-30 10:00

    Try this:

        static void Main(string[] args)
        {
            int partLength = 35;
            string sentence = "Silver badges are awarded for longer term goals. Silver badges are uncommon.";
            string[] words = sentence.Split(' ');
            var parts = new Dictionary<int, string>();
            string part = string.Empty;
            int partCounter = 0;
            foreach (var word in words)
            {
                if (part.Length + word.Length < partLength)
                {
                    part += string.IsNullOrEmpty(part) ? word : " " + word;
                }
                else
                {
                    parts.Add(partCounter, part);
                    part = word;
                    partCounter++;
                }
            }
            parts.Add(partCounter, part);
            foreach (var item in parts)
            {
                Console.WriteLine("Part {0} (length = {2}): {1}", item.Key, item.Value, item.Value.Length);
            }
            Console.ReadLine();
        }
    
    0 讨论(0)
  • 2020-11-30 10:00

    Joel there is a little bug in your code that I've corrected here:

    public static string[] StringSplitWrap(string sentence, int MaxLength)
    {
            List<string> parts = new List<string>();
            string sentence = "Silver badges are awarded for longer term goals. Silver badges are uncommon.";
    
            string[] pieces = sentence.Split(' ');
            StringBuilder tempString = new StringBuilder("");
    
            foreach (var piece in pieces)
            {
                if (piece.Length + tempString.Length + 1 > MaxLength)
                {
                    parts.Add(tempString.ToString());
                    tempString.Clear();
                }
                tempString.Append((tempString.Length == 0 ? "" : " ") + piece);
            }
    
            if (tempString.Length>0)
                parts.Add(tempString.ToString());
    
            return parts.ToArray();
    }
    
    0 讨论(0)
  • 2020-11-30 10:01

    This works:

    int partLength = 35;
    string sentence = "Silver badges are awarded for longer term goals. Silver badges are uncommon.";
    List<string> lines =
        sentence
            .Split(' ')
            .Aggregate(new [] { "" }.ToList(), (a, x) =>
            {
                var last = a[a.Count - 1];
                if ((last + " " + x).Length > partLength)
                {
                    a.Add(x);
                }
                else
                {
                    a[a.Count - 1] = (last + " " + x).Trim();
                }
                return a;
            });
    

    It gives me:

    Silver badges are awarded for 
    longer term goals. Silver badges 
    are uncommon. 
    
    0 讨论(0)
提交回复
热议问题