2013-06-27 6 views
3

У меня есть оператор foreach, где я просматриваю несколько строк из текстового файла, где я обрезал и отсортировал строки, которые мне нужны. То, что я хочу сделать, - подсчитать, сколько раз присутствует идентичная строка. Как мне это сделать?C# подсчет одинаковых строк из текстового файла

Вот мой код. Это второе if заявление, где я застрял:

 foreach (string line in lines.Where(l => l.Length >= 5)) 
     { 
      string a = line.Remove(0, 11); 

      if ((a.Contains(mobName) && a.Contains("dies"))) 
      { 

       mobDeathCount++; 
      } 
      if (a.Contains(mobName) && a.Contains("drops")) 
      { 
       string lastpart = a.Substring(a.LastIndexOf("drops")); 
       string modifiedLastpart = lastpart.Remove(0, 6); 

      } 

Вот что некоторые из линий выглядеть следующим образом:

мешок монет

siog бренди

мешок монет

мешок с монетами

th е Cath Щит

оборванный свиток

Так что им пытаются сделать, подсчитывая есть 3 линии с мешком монет. Но мне нужно сделать так, чтобы это могло быть все, theres список перечней, который огромный. Так косяк добавить все эм, заняло бы слишком долго

EDIT

private static void Main() 
    { 
     int mobDeathCount = 1; 
     int lootCheckCount = 1; 

     string[] lines = 
      System.IO.File.ReadAllLines(@"C:\Users\Michael\Documents\Electronic Arts\Dark Age of Camelot\chat.log"); 
     Console.WriteLine(
      "Enter which mob you want to see, remember to include the, for an example; The siog seeker, remember to start with a capital T"); 
     string mobName = Console.ReadLine(); 


     foreach (string line in lines.Where(l => l.Length >= 5)) 
     { 




      string a = line.Remove(0, 11); 

      if ((a.Contains(mobName) && a.Contains("dies"))) 
      { 

       mobDeathCount++; 
      } 
      if (a.Contains(mobName) && a.Contains("drops")) 
      { 
       string lastpart = a.Substring(a.LastIndexOf("drops")); 
       string modifiedLastpart = lastpart.Remove(0, 6); 

       var lineCountDict = modifiedLastpart.GroupBy(x => x).Where(x => x.Count() > 1).ToDictionary(x => x.Key, x => x.Count()); 
       foreach (var val in lineCountDict) 
       { 
        Console.WriteLine(val.Key + " - " + val.Value); 
       } 

новых линий;

[01:09:55] Искатель siog бросает мешок с монетами.

[01:09:55] Искатель siog бросает коньяк siog.

[01:09:55] Искатель siog умирает!

[1:09:55] Вы получаете 3687564 очки опыта. (1638917 бонуса лагеря)

[1:10:31] Вы бросаете Мало Покупается Извержение заклинания!

[01:10:31] Вы ударяете искателя siog за 424 (+18) урона!

[01:10:31] Искатель siog бросает мешок с монетами.

[01:10:31] Вы получаете 18 серебряных и 88 медных кусков.

[1:10:31] siog искатель умирает

+0

ли вы имеете в виду, сколько раз он присутствует в _single line_? – DonBoitnott

+1

Что такое «застряли» во втором заявлении? Из описания, 'mobDropCount ++' было бы достаточно, но я подозреваю, что вы заинтересованы в подсчете *, что * упал, нет? Для этого рассмотрим [Словарь ] (http://msdn.microsoft.com/en-us/library/xfhwa508.aspx), где имя сброшенной вещи - это ключ, а количество раз - это значение. Также ищите «C# частотную карту» или «C# гистограмму» на SO, так как многие подходы будут использовать словарь. – user2246674

+0

Нет, я имею в виду, если есть три строки, которые точно такие же, я могу подсчитать их. Надеюсь, что я сделаю свое ясное достаточно :) – Winkz

ответ

11

Вы можете использовать LINQ, чтобы получить количество повторяющихся строк. Это создаст словарь, содержащий строку в виде key, и количество строк, которое будет отображаться как value.

var lineCountDict = lines.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count()); 

Для считывания значений, просто перебирать словаря Таким образом, используя ваш пример списка

List<String> lines = new List<string>() 
    { 
     "a bag of coins", 
     "a siog brandy", 
     "a bag of coins", 
     "a bag of coins", 
     "the Cath Shield", 
     "a tattered scroll" 
    }; 

var lineCountDict = lines.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count()); 

foreach (var val in lineCountDict) 
{ 
    Console.WriteLine(val.Key + " - " + val.Value); 
} 

Это будет выводить каждую струну и сколько раз она появилась, в том числе и те строки, которые появляются только один раз ,Если вы хотите только те, которые являются дубликатами, вы можете изменить запрос LINQ, добавив пункт Where

var lineCountDict = lines.GroupBy(x => x).Where(x => x.Count() > 1).ToDictionary(x => x.Key, x => x.Count()); 

Словарь будет иметь только один элемент из списка в вашем примере (a bag of coins) и ключ будет a bag of coins и значение будет 3, так как оно появляется 3 раза.

обновление на основе комментариев

Это должно работать в вашем случае

List<string> modifiedList = new List<string>(); 
int numberOfDrops = 0; 

foreach (string line in lines.Where(l => l.Length >= 5)) 
{ 
    string ad = line.Remove(0, 11); 

    if ((ad.Contains(mobName) && ad.Contains("dies"))) 
    { 
     mobDeathCount++; 
    } 
    if (ad.Contains(mobName) && ad.Contains("drops")) 
    { 
     string lastpart = ad.Substring(ad.LastIndexOf("drops")); 
     string modifiedLastpart = lastpart.Remove(0, 6); 
     modifiedList.Add(modifiedLastpart); 
     numberOfDrops++; 
    } 

} 

double deathDropRatio = (double)mobDeathCount/(double)numberOfDrops; 

var lineCountDict = modifiedList.GroupBy(x => x).Where(x => x.Count() > 1).ToDictionary(x => x.Key, x => x.Count()); 

foreach (var val in lineCountDict) 
{ 
    Console.WriteLine(val.Key + " - " + val.Value); 
} 
+0

Не могу на самом деле заставить это работать, немного больше поможет с ним: D – Winkz

+0

Есть ли ошибка? – keyboardP

+1

Да, я получаю это, когда пытаюсь напечатать строкуCountDict из System.Collection.Generic.Dictionary'2 [System.String, System.Int32] – Winkz

3

Я хотел бы использовать словарь для этого.

Dictionary<string, int> dict = new Dictionary<string, int>(); 
foreach (string s in yourStringList) { 
    if (dict.ContainsKey(s)) { 
     dict[s] = ++dict[s]; 
    } else { 
     dict[s] = 1; 
    } 
} 

Ваши строки являются ключевыми словами словаря, и количество раз, которое каждый раз появляется, является значением.

(Отказ от ответственности: не проверял код, может потребовать небольших правок.)

+0

Пробовал то, что вы написали, но я получаю сообщение об ошибке со строкой s в цикле foreach, он говорит, что я не могу преобразовать тип элемента 'char' в тип итератора 'string' .. не уверен, что это значит – Winkz

+0

Это происходит во время выполнения или компиляции время? – Tenner

+0

Дает мне ошибку в поле ошибки, так что угадайте время компиляции? – Winkz

1

Я думаю, что это то, что вы хотите:

Dictionary<string, int> dropsDict = new Dictionary<string, int>();  

foreach (string line in lines.Where(l => l.Length >= 5)) 
{ 
    string a = line.Remove(0, 11); 

    if ((a.Contains(mobName) && a.Contains("dies"))) 
    { 
     mobDeathCount++; 
    } 

    if (a.Contains(mobName) && a.Contains("drops")) 
    { 
     string lastpart = a.Substring(a.LastIndexOf("drops")); 
     string modifiedLastpart = lastpart.Remove(0, 6); 

     if (dropsDict.ContainsKey(modifiedLastpart)) 
     { 
      dropsDict[modifiedLastpart] = dropsDict[modifiedLastpart]++; 
     } 
     else 
     { 
      dropsDict[modifiedLastpart] = 1; 
     } 
    } 
} 
+0

Спасибо за ваши усилия, хотя я не уверен на 100%, как работает ваш код, я ввел его, но я не могу заставить его работать так, как я хочу. Вы знаете, сколько из каждой подобной линии есть. – Winkz

+0

после выполнения этого кода вы можете проверить внутри словаря, чтобы найти количество капель для каждого элемента. поэтому, если одна из капель - «Большой кинжал», вы можете проверить dropDict [«Большой кинжал»], и это даст вам количество больших кинжалов, которые были сброшены. Тем не менее, я уверен, что есть больше изменений, чем просто имя элемента, поэтому это может быть более сложным. – Dodecapus

+0

Я сделал так, что линии, с которыми я работаю, начинаются с или, а затем и с именем элемента .. как кинжал или меч чего-то и т. Д. – Winkz

0

Если вы пытаетесь найти, сколько строк совпадают во всех массива строк (я имею в виду как - «строка один» появляется в 2 раза - и - «строка два» появляется 4 раза), создать словарь вне Еогеасп и первое, что внутри Еогеасп место это:

Dictionary<string, int> same = new Dictionary<string, int>(); 

foreach (string line in lines) 
{ 
     if (same.ContainsKey(line)) 
      ++same[line]; 
     else 
      same.Add(line, 1); 

     //...... 
     //do your other stuff 
} 

Каждыйстрока, которая повторяется, будет обновлена ​​в значении словаря (внутри словаря будут записаны все строки и сколько раз они появлялись), с помощью которых вы можете проверить, сколько раз появлялась определенная строка.

+0

Как я могу получить результат из этого? – Winkz

0

Возможно, это может вам помочь, это кусок кода, который подсчитывает все повторяющиеся строки в коллекции. Вы должны изменить его в соответствии с вашими потребностями, но надеюсь, что вы это решаете.

var allStrings = new List<string>{"stringOne", "stringOne", "stringTwo", "stringOne", "stringThree", "stringTwo"}; 
    var allStringsGrouped = allStrings.GroupBy(i => i); 
    foreach (var group in allStringsGrouped) 
    { 
     System.Diagnostics.Debug.WriteLine(group.Key +" occured " + group.Count() + " times"); 
    } 

Выход заключается в следующем:

stringOne occured 3 times 
stringTwo occured 2 times 
stringThree occured 1 times 
+0

Спасибо, но дело в том, что для меня нужно вводить все разные линии, на которые потребуется огромное количество времени. – Winkz

Смежные вопросы