0

I have a list of items which have names and I need to iterate them, but I also need to know how many times this item with the same name it is. So this is an example:

-----
|1|A|
|2|B| 
|3|C| 
|4|C| 
|5|C| 
|6|A| 
|7|B| 
|8|C| 
|9|C|
-----

So, when I'm iterating and I'm on row 1, I want to know it is the first time it is an A, when I'm on row 6, I want to know it is the second time, when I'm on row 9, I want to know it is the 5th C, etc. How can I achieve this? Is there some index I can keep track of? I was also thinking of filling a hash while iterating, but perhaps thats too much.

John
  • 6,404
  • 14
  • 54
  • 106
  • 1
    This feels like a XY Problem - https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem . If your input is the set of letters as shown in your question, what **result** are you aiming to receive? e.g. are you wanting the count of each letter? The first index of each letter? All indexes for each letter? Something else? – mjwills Aug 27 '18 at 05:24
  • When iterating I want to know that it is e.g. the 3rd C, so I know I need to get the third C from another list and not the first or second. – John Aug 27 '18 at 05:25
  • It would be awesome if you could provide a [mcve] so we can see the contents of this other list. This may help us find better solutions for your context. – mjwills Aug 27 '18 at 05:26
  • if you only want a count of item by group then you can use Linq for it – Jack Gajanan Aug 27 '18 at 05:34

4 Answers4

1

You can use Dictionary<char, int> for keeping count of each character in your list

here your key will be character and value will contain number of occurrences of that character in list

    Dictionary<char, int> occurances = new Dictionary<char, int>();
    List<char> elements = new List<char>{'A', 'B','C','C','C','A','B', 'C', 'C'};
    int result = 0;
    foreach(char element in elements)
    {
        if(occurances.TryGetValue(element, out result))
            occurances[element] = result + 1;
        else
            occurances.Add(element, 1);
    }

    foreach(KeyValuePair<char, int> kv in occurances)
        Console.WriteLine("Key: "+ kv.Key + " Value: "+kv.Value);

Output:

Key: A Value: 2
Key: B Value: 2
Key: C Value: 5

POC: dotNetFiddler

Prasad Telkikar
  • 15,207
  • 5
  • 21
  • 44
1

Use dictionary to keep track of counter.

List<string> input = new List<string> { "A", "B", "C", "C", "C", "A", "B", "C", "C" };

            Dictionary<string, int> output = new Dictionary<string, int>();
            foreach(var item in input)
            {
                if (output.ContainsKey(item))
                {
                    output[item] = output[item] + 1;
                }
                else
                {
                    output.Add(item, 1);
                }
            }
Amit Kumar
  • 5,888
  • 11
  • 47
  • 85
  • Thanks @AmitKumar, this is something I can work with – John Aug 27 '18 at 05:28
  • https://stackoverflow.com/questions/9382681/what-is-more-efficient-dictionary-trygetvalue-or-containskeyitem may be worth a read. – mjwills Aug 27 '18 at 06:01
0

I think you'll need a reversed index instead of row store index.

Row store index just like your table described, and reversed index store terms to search indexes. Probably like this:

A 1,6

B 2,7

C 3,4,5,8,9

The search engine such like 'Elastic search/Solr' will store terms like this.

If you are in C#, Dictionary<string, List<int>> is pretty much good for you. There you can keep your data that is reverse indexed.

Lei Chi
  • 216
  • 1
  • 14
-1

The clean way is to implement your own list; the item is your own object. By this method, you implement your own Iterator pattern with an additional property in your object and your own Add() method. The new Iterator should inherit List and should override the Add() method of List. I implement this for my own. you can use it. keep in mind, this solution is one of some solutions that exist. However, I think this is one the best solutions with respect to SOLID and OO principals.

public class CounterIterator : List<Item>
{
    public new void Add(Item item)
    {
        base.Add(item);
        foreach (var listItem in this)
        {
            if (listItem.Equals(item))
            {
                item.CountRepeat++;
            }
        }
    }
}

public class Item
{
    public Item(string value)
    {
        Value = value;
    }
    public string Value { get; private set; }
    public int CountRepeat { get; set; }
    public override bool Equals(object obj)
    {
        var item = obj as Item;
        return item != null && Value.Equals(item.Value);
    }
}

I tested the code above. It is an extension of List which has an added behavior. If anyone thinks it is not a correct answer, please mention me in comments. I will try to clarify the issue.