2016-07-28 85 views
0

我不明白为什么我在下面的Where子句中得到它。为什么我在这里得到IndexOutOfRangeException?

using System; 
using System.Linq; 

public static class Extensions 
{ 
    /// <summary> 
    /// Removes consecutive characters, 
    /// e.g. "aaabcc" --> "abc" 
    /// </summary> 
    public static void RemoveDuplicates(this string s) 
    { 
     var arr = s.ToCharArray() 
        .Where((i,c) => (i > 0) ? (c != s[i - 1]) : true) 
        .ToArray(); 
     s = new string(arr); 

    } 
} 


public class Program 
{ 
    public static void Main() 
    { 
     var str = "aaabcc"; 
     str.RemoveDuplicates(); 
     Console.WriteLine(str); 
    } 
} 

此外,有没有办法让这个稍微更有效率和紧凑,同时仍然使用LINQ?

+0

我认为这是另一种方式,第一个元素是char,第二个是索引。所以把'(i,c)切换到(c,i)' –

回答

1

你很可能需要重新广告的使用Docs方法或一种特殊的过载之前:

类型:System.Func<TSource, Int32, Boolean>

测试一个条件的每个源元件的功能;该函数的第二 参数表示源元素的索引

所以,你的代码应该是这样的:

.Where((item, index) => (index > 0) ? (item != s[index - 1]) : true) 
5

你的参数错误的顺序在这里:

.Where((i, c) => (i > 0) ? (c != s[i - 1]) : true) 

应该变成:

.Where((c, i) => (i > 0) ? (c != s[i - 1]) : true) 
1

你可以使用Distinct方法已经不是你自己的方法用于此目的:

var str = "aaabcca"; 
var result = string.Join("",str.ToCharArray().Distinct()); 

结果:

“ABC”

编辑:如果你想删除的顺序重复,你可以试试这个代码,而不是:

var removesequential = string.Join("",str.Where((c, i) => i == 0 || c != str[i - 1])); 

结果:

“ABCA”

+2

尽管'Distinct'做了一些不同的事情,他的代码试图去除连续的重复,但不同的是全局重复。 –

+0

@ LasseV.Karlsen谢谢。我更新了我的答案。 –

2

的误差是(I,C)在其中。

您使用以下可枚举扩展(See MSDN)

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source, 
    Func<TSource, int, bool> predicate) 

注意,在FUNC指数是第二参数。

我认为最快的方法不会使用LINQ,但将是一个字符串扩展:

public static string RemoveDuplicates(this string s) 
{ 
    if (String.IsNullOrEmpty(s)) return String.Empty(); // optional: return null 

    var resultBuilder = new StringBuilder(s.Length); 
    resultBuilder.Append(s.First()); 
    for (int i=1; i< s.Length; ++i) 
    { 
     if (s[i] != s[i-1]) 
      resultBuilder.Append(s[i]); 
    } 
    return resultBuilder.ToString(); 
} 

但是,如果你真的想因为要附加其他的LINQ语句,你使用LINQ,例如,可以模仿上述行为如下,同时仍然使用延迟加载:

public static string RemoveDuplicates(this string s) 
{ 
    if (String.IsNullOrEmpty(s)) return String.Empty(); 
    s.AsEnumerable().Take(1) 
     .Concat(s.AsEnumerable().Skip(1) 
      .where((c, i) => c != s[i])); 
} 
  • 注意,因为检查的字符串不是空的,我敢肯定,有第一()。
  • 由于Skip(1),where语句中的索引0等于s [1],并且索引i等于i> 0时的s [i-1]。
相关问题