代码之家  ›  专栏  ›  技术社区  ›  Mike Cole

用C语言构建智能字符串修剪函数#

  •  10
  • Mike Cole  · 技术社区  · 14 年前

    public static string SmartTrim(this string s, int length)
            {
                StringBuilder result = new StringBuilder();
    
                if (length >= 0)
                {
                    if (s.IndexOf(' ') > 0)
                    {
                        string[] words = s.Split(' ');
                        int index = 0;
    
                        while (index < words.Length - 1 && result.Length + words[index + 1].Length <= length)
                        {
                            result.Append(words[index]);
                            result.Append(" ");
                            index++;
                        }
    
                        if (result.Length > 0)
                        {
                            result.Remove(result.Length - 1, 1);
                        }
                    }
                    else
                    {
                        result.Append(s.Substring(0, length));
                    }
                }
                else
                {
                    throw new ArgumentOutOfRangeException("length", "Value cannot be negative.");
                }
    
                return result.ToString();
            }
    
    7 回复  |  直到 14 年前
        1
  •  14
  •   Jon Skeet    14 年前

    我会用 string.LastIndexOf -至少如果我们只关心空间。那么就不需要创建任何中间字符串。。。

    public static string SmartTrim(this string text, int length)
    {
        if (text == null)
        {
            throw new ArgumentNullException("text");
        }
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException();
        }
        if (text.Length <= length)
        {
            return text;
        }
        int lastSpaceBeforeMax = text.LastIndexOf(' ', length);
        if (lastSpaceBeforeMax == -1)
        {
            // Perhaps define a strategy here? Could return empty string,
            // or the original
            throw new ArgumentException("Unable to trim word");
        }
        return text.Substring(0, lastSpaceBeforeMax);        
    }
    

    测试代码:

    public class Test
    {
        static void Main()
        {
            Console.WriteLine("'{0}'", "foo bar baz".SmartTrim(20));
            Console.WriteLine("'{0}'", "foo bar baz".SmartTrim(3));
            Console.WriteLine("'{0}'", "foo bar baz".SmartTrim(4));
            Console.WriteLine("'{0}'", "foo bar baz".SmartTrim(5));
            Console.WriteLine("'{0}'", "foo bar baz".SmartTrim(7));
        }
    }
    

    结果:

    'foo bar baz'
    'foo'
    'foo'
    'foo'
    'foo bar'
    
        2
  •  2
  •   driis    14 年前

    基于Regex的解决方案怎么样?您可能还想测试一些,并进行一些边界检查;但我想到的是:

    using System;
    using System.Text.RegularExpressions;
    
    namespace Stackoverflow.Test
    {
        static class Test
        {
            private static readonly Regex regWords = new Regex("\\w+", RegexOptions.Compiled);
    
            static void Main()
            {
                Console.WriteLine("The quick brown fox jumped over the lazy dog".SmartTrim(8));
                Console.WriteLine("The quick brown fox jumped over the lazy dog".SmartTrim(20));
                Console.WriteLine("Hello, I am attempting to build a string extension method to trim a string to a certain length but with not breaking a word. I wanted to check to see if there was anything built into the framework or a more clever method than mine".SmartTrim(100));
            }
    
            public static string SmartTrim(this string s, int length)
            {
                var matches = regWords.Matches(s);
                foreach (Match match in matches)
                {
                    if (match.Index + match.Length > length)
                    {
                        int ln = match.Index + match.Length > s.Length ? s.Length : match.Index + match.Length;
                        return s.Substring(0, ln);
                    }
                }
                return s;
            }
        }
    }
    
        3
  •  2
  •   kbrimington    14 年前

    试试这个。它是空安全的,如果长度比字符串长就不会中断,并且涉及的字符串操作更少。

    编辑: 根据建议,我删除了中间字符串。我将保留答案,因为在不需要例外的情况下,它可能很有用。

    public static string SmartTrim(this string s, int length)
    {
        if(s == null || length < 0 || s.Length <= length)
            return s;
    
        // Edit a' la Jon Skeet. Removes unnecessary intermediate string. Thanks!
        // string temp = s.Length > length + 1 ? s.Remove(length+1) : s;
        int lastSpace = s.LastIndexOf(' ', length + 1);
        return lastSpace < 0 ? string.Empty : s.Remove(lastSpace);
    }
    
        4
  •  1
  •   XstreamINsanity    14 年前
    string strTemp = "How are you doing today";
    int nLength = 12;
    strTemp = strTemp.Substring(0, strTemp.Substring(0, nLength).LastIndexOf(' '));
    

    我认为应该这样做。当我运行时,它以“你好”结束。

    所以你的功能是:

    public static string SmartTrim(this string s, int length) 
    {  
        return s.Substring(0, s.Substring(0, length).LastIndexOf(' '));; 
    } 
    

    不过,我肯定会添加一些异常处理,比如确保整数长度不大于字符串长度且不小于0。

        5
  •  1
  •   driis    14 年前

    如果您只关心将空格作为单词边界,则必须使用LINQ one liner:

    return new String(s.TakeWhile((ch,idx) => (idx < length) || (idx >= length && !Char.IsWhiteSpace(ch))).ToArray());
    
        6
  •  1
  •   hazjack    9 年前

    像这样使用

    var substring = source.GetSubstring(50, new string[] { " ", "." })

    此方法可以基于一个或多个分隔符获取子字符串

    public static string GetSubstring(this string source, int length, params string[] options)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                return string.Empty;
            }
    
            if (source.Length <= length)
            {
                return source;
            }
    
            var indices =
                options.Select(
                    separator => source.IndexOf(separator, length, StringComparison.CurrentCultureIgnoreCase))
                    .Where(index => index >= 0)
                    .ToList();
    
            if (indices.Count > 0)
            {
                return source.Substring(0, indices.Min());
            }
    
            return source;
        }
    
        7
  •  0
  •   joshperry    14 年前

    尽管其他人已经充分回答了这一点,我还是要说一些灵巧的话:

    public string TrimString(string s, int maxLength)
    {
        var pos = s.Select((c, idx) => new { Char = c, Pos = idx })
            .Where(item => char.IsWhiteSpace(item.Char) && item.Pos <= maxLength)
            .Select(item => item.Pos)
            .SingleOrDefault();
    
        return pos > 0 ? s.Substring(0, pos) : s;
    }
    

    我省略了参数检查,其他人只需强调重要的代码。。。