2010-01-02 130 views
0

我对C#编程相当陌生,而且我被困在了我的小ASP.NET项目中。计算数组中字符串的出现次数,然后删除重复项

我的网站目前检查针对URL的Twitter状态,然后添加这些网址到阵列,所有这些都通过一个正则表达式模式匹配过程。很明显,不止一个人会使用特定的URL更新a,所以我不想列出重复项,并且我想要统计特定URL在100个推文中被提及的次数。

现在我有一个List<String>,我可以排序,使所有重复的URL是彼此相邻。我的印象是,我可以将list[i]list[i+1]进行比较,如果它们匹配,则将计数器添加到(count ++)中,如果它们不匹配,则将URL和计数值添加到新的数组,假设这是重复项的结尾。

这将消除重复的,给我的出现对每个URL的数量的计数。目前,我所拥有的并不是工作,我不知道为什么(就像我说的,我对此并不是很有经验)。

用下面的代码,假设JSON馈送已搜索用关键字成srchResponse.results。其中包含URL的结果将被添加到sList,这是一个字符串List类型,其中只包含网址,而不包含整个消息。

我想把每个URL(无重复)中的一个,一个URL出现次数的计数整数(以字符串),以及用户名,消息和用户图像URL全部放入我称为'网址[100] []”。我已经制作了100行长的阵列,以确保一切都可以适合,但通常情况下,这太大了。每个'行'将有5个元素。

调试器卡住就行了:if (sList[i] == sList[i + 1])这是我的想法的关键所在,所以清楚的逻辑是行不通的。任何建议或任何事情都将被认真赞赏!

下面是示例代码:

var sList = new ArrayList(); 

    string[][] urls = new string[100][]; 

    int ctr = 0; 
    int j = 1; 

    foreach (Result res in srchResponse.results) 
    {   

     string content = res.text; 
     string pattern = @"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)"; 
     MatchCollection matches = Regex.Matches(content, pattern); 

     foreach (Match match in matches) 
     { 

     GroupCollection groups = match.Groups; 

        sList.Add(groups[0].Value.ToString()); 
     } 
    } 

    sList.Sort();  
    foreach (Result res in srchResponse.results) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      if (sList[i] == sList[i + 1]) 
      { 
       j++; 
      } 
      else 
      { 
       urls[ctr][0] = sList[i].ToString(); 
       urls[ctr][1] = j.ToString(); 
       urls[ctr][2] = res.text; 
       urls[ctr][3] = res.from_user; 
       urls[ctr][4] = res.profile_image_url; 
       ctr++; 
       j = 1; 
      } 
     } 



    } 

然后,代码进到每个结果添加到与所述HTML一个StringBuilder方法。

现在是edite

+1

您能够利用LINQ(即可以使用3.0版本的框架)?它可以做你正在问的约1行代码:) – 2010-01-02 18:25:42

+0

我使用3.5框架...你能给我一个实现LINQ或我可以找到更多的例子? – Alex 2010-01-02 18:30:45

+0

不错的例子:http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx - 更具体到这个例子:http://msdn.microsoft.com/en-us/vcsharp/aa336754.aspx# simple1 – 2010-01-02 18:32:26

回答

8

你的算法的描述看起来很好。我不知道实施有什么问题;我没有仔细阅读。 (您正在使用一个ArrayList,这是一即时红旗,你为什么不使用更强类型的泛型集合?)

不过,我有一个建议。这正是LINQ打算解决的问题。您不必自己编写所有容易出错的代码,只需要描述您对感兴趣的转换,并让编译器为您解决。

假设你有一个字符串列表,并且希望确定每个出现的次数:

var notes = new []{ "Do", "Fa", "La", "So", "Mi", "Do", "Re" }; 

var counts = from note in notes 
      group note by note into g 
      select new { Note = g.Key, Count = g.Count() } 

foreach(var count in counts) 
    Console.WriteLine("Note {0} occurs {1} times.", count.Note, count.Count); 

,我希望你同意更容易比你写的所有阵列逻辑阅读。当然,现在你有你的顺序独特的项目;你有一系列的计数,每个计数都包含一个唯一的注释。

+0

非常有趣和有帮助... LINQ我现在意识到是我解决这个问题的方法。什么是更强类型的通用集合?你是指我自己定义的一个集合(一组使用内部属性进行比较的对象?) 再次感谢Eric,好东西。 – Alex 2010-01-02 18:49:29

+0

看起来我错过了发布其他答案的通知。我将删除我的代替这个响应... – 2010-01-02 18:50:00

+1

@AlexW - 在这种情况下'List '将是你需要的强类型泛型集合,因为URL列表将明确包含字符串和唯一字符串(显然更多泛型不是这样,但这是一个简单的解释)。 'ArrayList.Add()'需要'对象'类型,它可以是任何从'object'继承的东西(这恰好是.NET中的所有东西)!好教程:http://www.c-sharpcorner.com/UploadFile/jgodel/Page102062006170216PM/Page1.aspx – 2010-01-02 18:55:54

1

我建议使用比数组更复杂的数据结构。一套将保证你没有重复。

看起来像C#集合不包括Set,但有第三方实现可用,如this one

+0

@duffymo - 有一个集合结构,它叫做'HashSet <>',它是在.NET 3.5中引入的。他们无法将其设置为Set,因为这可能与Visual Basic中的“Set”关键字冲突。 – 2010-01-02 18:38:54

+0

谢谢,约翰。命名空间不能将这个问题排序吗?我认为那就是它的原因。是否还有TreeSet或其他实现? – duffymo 2010-01-02 19:02:48

+0

@duffymo - 在VB中'Set'是一个关键字(就像'for'或'if'),所以名称空间的改变不会有帮助。我相信在这一点上没有其他的实现,因为没有一个集合的接口,但结构本身并没有密封,所以可能会有更多。看起来好像在.NET 4.0中,他们正在创建一个“ISet”接口,这将允许其他实现。 – 2010-01-02 19:45:30

0

您的循环失败,因为当我== 99,(i + 1)== 100它超出了你的数组边界。

但正如其他人所指出的,.net 3.5有更好的方式来做你想做的事情。

+0

我确实尝试过使用较低的值,例如我<40,但它仍然没有工作! – Alex 2010-01-02 18:58:37

+0

然后发生的事情是它说urls [ctr] [1] = j.ToString();有一个错误:空引用异常... ??? 我还是很困惑!我会尝试使用LINQ并重写整个事件 – Alex 2010-01-02 19:01:23

+0

也许如果我重写ToString方法,这将适用于我的整数j = 1; – Alex 2010-01-02 19:02:10

0

如果你不需要知道有多少重复的特定条目,你可以做到以下几点:

LINQ扩展方法

.Count() 
.Distinct() 
.Count() 
相关问题