-1

I have a class named ClusterMember as:

public class ClusterMember
{
        public string _name;

        public ClusterMember(string _name)
        {
            this._name = _name;
        }

        public string _Name
        {
            get { return _name; }

            set { _name = value; }
        }
}

public class Cluster
{
        private Dictionary<int, List<ClusterMember>> _dic;

        public Cluster(Dictionary<int, List<ClusterMember>> _dic)
        {   
            this._dic = _dic;
        }

        public Dictionary<int, List<ClusterMember>> _Dictionary
        {
            get { return _dic; }

            set { _dic = value; }
        }

        // adding members to clusters
        public void AddToCluster(int _id, ClusterMember _clusMem)
        {
            // checks if cluster with specific id is already in Dictionary
            if (!_dic.ContainsKey(_id))
            {
                _dic.Add(_id, new List<ClusterMember>());
            }
            else
            {
                _dic[_id].Add(_clusMem);
            }
        }

        // get members count for specific cluster id
        public int GetCount(int id)
        {
            return _dic[id].Count;
        }

        // get members count for all clusters
        public Dictionary<int, int> GetCounts()
        {
            return _dic.ToDictionary(k => k.Key, v => v.Value.Count);
        }

       public void Print_Clusters(List<Cluster> _clusterToPrint, double _alpha, int _length)
       {
            Console.WriteLine("\n" + "Number of Customers = " + _length + "\n");
            Console.WriteLine("\n" + "Alpha = " + _alpha + "\n");
            Console.WriteLine("\n" + "Number of Clusters = " + _clusterToPrint.Max() + "\n");  

            foreach ( var _clusters in _clusterToPrint  )
            {
                Console.WriteLine("Cluster ID {0} - ClusterMember {1}", _clusters._Dictionary.Keys, _clusters._Dictionary.Values);
                Console.Write("\n");
            }
            Console.ReadLine();
       }
}  

When I use these classes in this method as:

public static void DP_Cluster(List<string> _cust, double _alpha)
{
        var _customer = new List<string>();
        var _currentTables = 0;     // current number of tables i.e. "k"

        var _dicInitial = new Dictionary<int, List<ClusterMember>>();
        var _customerNumber = 0;    // running customer number i.e. "n"

        var _probOld = new Dictionary<int, double>();
        //var _probOld = new List<Double>();         // porbability to be in Old cluster
        var _probNew = 0.0;         // porbability to be in New cluster 

        List<Cluster> _myClusters = new List<Cluster>();

        Cluster _cluster = new Cluster(_dicInitial); 
        // add first customer from "_cust" list directly to a new cluster
        _cluster.AddToCluster(++_currentTables, new ClusterMember(_cust.ElementAt(_customerNumber)));

        _myClusters.Add(_cluster);
        _probOld.Add(_currentTables, Convert.ToDouble(1) / Convert.ToDouble(1 + _alpha));

        for (int _i = 1; _i < _cust.Count - 1; _i++)
        {
            if (_i <= _currentTables)
            {
                // get customer Count in Cluster i / customerNumber + alpha
                // Got ERROR here at "_myClusters[_i]"
                double _probOldValue = _myClusters[_i].GetCount(_i) / ((_i + 1) - 1 + _alpha);  

                    _probOld.Add(_currentTables, _probOldValue);
                }
            else if ( _i == _currentTables + 1)
            {
                _probNew =_alpha / ((_i + 1) - 1 + _alpha);
                _currentTables++;
                _probOld.Add(_currentTables, _probNew);
            }

            List<int> _keyList = new List<int>(_probOld.Keys);
            Random _random = new Random();
            int _randomKey = _keyList[_random.Next(_keyList.Count)];
                        _cluster.AddToCluster(_randomKey, new ClusterMember(_cust.ElementAt(_i)));
        }
        _myClusters.Add(_cluster);

        _cluster.Print_Clusters(_myClusters, _alpha, _cust.Count);

}
public static List<string> GetRandomString(int _numOfStrings, int _stringLength)
{
        string[] _arrStr = new string[_numOfStrings];
        List<string> _listSt;
        const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var _random = new Random();

        for (int _i = 0; _i < _arrStr.Length; _i++)
        {
            _arrStr[_i] = new string(Enumerable.Repeat(_chars, _stringLength).Select(s => s[_random.Next(s.Length)]).ToArray());
        }
        _listSt = new List<string>(_arrStr);
        return _listSt;
}

static int Main()
{
      double _alfa = 5;
      int _n = 30;      
      List<string> _data = GetRandomString(_n, 8);
      DP_Cluster(_data, _alfa);
      return 0;
}

The ERROR is:

Index was out of range. Must be non-negative and less than the size of the collection.
whereas I have added ++_currentTables in _cluster i.e. object of class Cluster here it should be 1 which is not out of range.

I'm wanting to take the Count at specific cluster id which has been added already in List whereas the error is demanding less than size of index value. I think the value which I have inserted at this line:

_cluster.AddToCluster(++_currentTables, new ClusterMember(_cust.ElementAt(_customerNumber)));  

I have inserted 1 i.e. (_++currentTables) as first index of _dic member of class i.e. Cluster whereas by default it should start with 0.

Is this an error of index insertion? But I want to start the cluster number with 1 not with 0. How to sort out this error?

maliks
  • 1,102
  • 3
  • 18
  • 42
  • 6
    Please tell us the line it occurs on – Rob Apr 11 '16 at 11:23
  • @Sinatr its not the duplicate of your mentioned link – maliks Apr 11 '16 at 11:25
  • 1
    @Rob I can't mention the line number here but it is this line `double _probOldValue = _myClusters[_i].GetCount(_i) / ((_i + 1) - 1 + _alpha);` – maliks Apr 11 '16 at 11:27
  • 1
    Can you put a break point on that line and tell us what `_i` is and how big `_myClusters` is? Also, why are you using the same index for both `_myClusters` and `GetCount`? – doctorlove Apr 11 '16 at 11:28
  • This: `for (int _i = 1; _i < _cust.Count - 1; _i++)` doesn't make sense for a `1-indexed` collection. If `_cust` has one element, then you're writing `1 < 1 - 1` which will never execute. It should be `i <= _cust.Count`. This leads me to believe that it's not failing for `i=1`, but another value. Please debug it – Rob Apr 11 '16 at 11:32
  • @maliks, see accepted answer of duplicate link. It has multiple cases when you can get this exception pretty well explained (if you want **exact** duplicate with same message, then [sure](http://stackoverflow.com/q/24812679/1997232), you will *reach* duplicate few clicks after). Otherwise it's a "I don't know how to debug" question (based on given amount of code). Put breakpoint, check all variables and see for yourself what is wrong before you get this exception. – Sinatr Apr 11 '16 at 11:33
  • 1
    You're not checking if `_i` is less than `_myClusters.Count`, you're only checking `_i` against `_cust.Count - 1`. In other words: you're checking if you have enough apples, but you then proceed to take an orange. – Pieter Witvoet Apr 11 '16 at 11:35
  • @PieterWitvoet Nice catch – Rob Apr 11 '16 at 11:37
  • @Rob still same error whereas I have made change suggested by you – maliks Apr 11 '16 at 11:38
  • @doctorlove I have put a break point but can't get what `_i` is at that stage because error raised, I'm using same index for both `_myClusters` and `GetCount` because I want to get count of current cluster – maliks Apr 11 '16 at 11:40
  • @PieterWitvoet `_myClusters` is a list of clusters from where I want to get count (number of cluster members) of current cluster i.e. `_i` whereas I have to assign each customer to a cluster for which I'm checking `_i` for `_cust.Count - 1` and reason of `_cust.Count - 1` is because we have already assigned the first customer to a cluster – maliks Apr 11 '16 at 11:48
  • @Sinatr I know how to debug whereas I have copied this error from debug box after debugging, can you please specifically look at the problem which I have elaborated at end of the question – maliks Apr 11 '16 at 11:55
  • 1
    *"I know how to debug"* - if you would there would be no question, or question would be just one line with all variables values listed (in case if you suspect a bug in framework). Currently you are not showing confidence in that your code is right. Why? Because you haven't debug it to check what all assumption you made are correct. If you want someone else to debug, then please provide [mcve](http://stackoverflow.com/help/mcve). Current code is not sufficient to debug (e.g. `_probNewValue` definition is missing and we don't know how to run your code, it's long, etc.). – Sinatr Apr 11 '16 at 12:00
  • @maliks: If you're accessing `myClusters[i]` then you'd better make sure that `i` is less than `myClusters.Count`. Whether `i` is also less than `cust.Count` may be important elsewhere, but it doesn't matter for the `myClusters[i]` access. In fact, `myClusters` only contains a single item when you start that for loop, but during the first iteration you're trying to access the item at index 1 (the second item), so it will fail immediately. – Pieter Witvoet Apr 11 '16 at 12:04
  • @Sinatr is it fine now? I have provided almost.... – maliks Apr 11 '16 at 12:15
  • @PieterWitvoet I don't want to start the _cluster numbering_ with 0, how to store first customer at index `1`? – maliks Apr 11 '16 at 12:15
  • @maliks: just don't reuse indexes as cluster numbers? Keep them separate. Just because an object is stored at a certain index in a certain list somewhere doesn't mean that it's ID needs to match that index. Bytheway, there's also another index-out-of-bounds problem: `_cust.ElementAt(_customerNumber)` will throw if an empty list is passed to your function. – Pieter Witvoet Apr 11 '16 at 12:23
  • @PieterWitvoet I'm not using indexes as cluster numbers but `List` is custom typed list having a `Dictionary` as a member of _class_ `Cluster` to store the _clusters_ information. Moreover `_cust.ElementAt(_customerNumber)` will not throw exception because list will never be empty in my case which is being passed to function. – maliks Apr 11 '16 at 12:42
  • That assumption is not documented or asserted anywhere, as far as I can see, so I don't think it's safe to write code in such a way. Requirements change over time, and we tend to forget the details of the code we wrote... Either way, yes, you are using indexes as cluster numbers: `_i` is used as an *index* in `_myClusters[_i]`, but is also used as an *id* when you call `GetCount(_i)`. – Pieter Witvoet Apr 11 '16 at 12:49
  • @PieterWitvoet but how to avoid this ? Whereas I need to count cluster members of current cluster i.e. _i – maliks Apr 11 '16 at 12:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108820/discussion-between-pieter-witvoet-and-maliks). – Pieter Witvoet Apr 11 '16 at 12:55
  • @PieterWitvoet your help needed – maliks Apr 28 '16 at 07:39
  • @PieterWitvoet I just ask you a single thing about `interface` we have created that day, are you there? – maliks May 02 '16 at 12:00

1 Answers1

0

Blindly running code throws exception at this line:

  1. _myCluster.Count is 1, means you can only access _myCluster[0]
  2. Value of _i is 1, so you are trying to access _myCluster[1], therefore exception.
  3. Error is probably that what you start _i from 1 (indexes are zero-based), perhaps you want to access _myCluster[i - 1], only you know.
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • @Sinatr--you right about this exception, but `_myCluster` is object of a custom typed _list_ i.e. `List` and index used in _class_ `Cluster` are _cluster numbers_ whereas I don't want to use `0` as _cluster number_, because of which this exception raised. Can you help in sorting out this? – maliks Apr 11 '16 at 12:37
  • I've no idea what are *cluster numbers*, but you can either: 1) change `_i` to start from `0`, but display it as `_i + 1` to see that *cluster number* 2) keep `_i` starting from `1`, but access `_myCluster[_i - 1]` to convert *cluster number* to valid index. Btw, read [this](https://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx), names beginning with underscore for local variables/parameters is not cool. I myself use `_` only for fields (obviously not public one) to be able to re-use same name (but without `_`) for naming parameters/local variables. – Sinatr Apr 11 '16 at 12:39
  • _cluster numbers_ are "how many total clusters are there in _class_ `Cluster` stored" – maliks Apr 11 '16 at 12:43
  • Than it's a `Count`, it has nothing to do with indexes. When `Count == 1` maximum index you can operate is `0`. When `Count == 0` you can't operate any index. – Sinatr Apr 11 '16 at 12:44
  • I have changed as `_myCluster[_i - 1]` but it is giving a count of `0` because value of `probOldValue` is showing `0.0` while debugging whereas it should show a count of `1` then value of `probOldValue` will not be `0.0` because there is one cluster in _class_ `Cluster` having one _cluster member_ currently i.e. _the first customer_ – maliks Apr 11 '16 at 12:50
  • That's another issue. My answer is regarding exception you were getting and I was rather interested to prove debugging usefulness, nothing else, sorry. – Sinatr Apr 11 '16 at 12:58
  • Perhaps you want to construct a custom type and [overload indexer](http://stackoverflow.com/q/287928/1997232) to access something via index, like it's not index. That way you wouldn't have `_myCluster` defined as `List`, but rather `ClusterHolder` and would write `_myCluster[1]` to access zero-indexed `ClusterItem`... – Sinatr Apr 11 '16 at 13:01