Robert Collins
Robert Collins

Reputation: 87

Best way of building a collection of unique ID's as well as their counts

I've looked into various different ways of array's, arraylist's, dictionaries... but as I'm used to PHP I'm not entirely sure on the best way I could collect the following information.

My program loops through each user, and if their is a location ID, I want to add that to some sort of collection / array. It's expected that different users will have the same location ID.

If the location ID is the same, I need to increase an integer of how many occurrence for that location ID.

Example:

User1 - Location1
User2 - Location3
User3 - Location3

Location1 = 1
Location3 = 2

Also I need to somehow append each user ID to this collection. So Location3 / 2 occurrences / user2/user3

I've been trying to figure out the best way of doing this for about two hours now, and all the different methods of multidimensional arrays, arraylists, dictionaries is all a little confusing as it all seems abstract to my PHP knowledge. I think C# handles arrays in an entirely different way.

Essentially, the collection with unique location ID's / occurrences / and users collection needs to be stored in something that can be passed to somewhere else in my program as an argument.

I've made a PHP script which does exactly what I'm after

foreach($call["data"] as $v)
{
    // Foreach USER ($v containing their unique ID and location ID.)

    $user_id        = $v["id"];
    $location_id    = $v["location"]["id"];

    // This adds the location ID as the key within the array, followed by every user who has it. I don't need a count in this case, as I could just count the number of users.
    $collection[$location_id][$user_id] = null;
}

This in return creates this array when printed using print_r

[106078429431815] => Array
(
    [620790873] => 
    [626276302] => 
    [100000152470577] => 
)

(Small part of the output). - Added PHP Example. Anyone know how I can get C# to collect the same information in the same way my PHP array does?

Upvotes: 2

Views: 299

Answers (4)

Konstantin Spirin
Konstantin Spirin

Reputation: 21271

var byLocation = users.Where(u => !string.IsNullOrEmpty(u.Location))
    .GroupBy(u => u.Location);

var stats = byLocation.Select(l => string.Format("{0} / {1} occurrences / {2}",
    l.Key, l.Count(), string.Join("/", l.Select(u => u.User)));

// And just to print the result
foreach (var location in stats)
    Console.WriteLine(location);

Upvotes: 0

Ryan Byrne
Ryan Byrne

Reputation: 860

Create an object to hold each item of data.

public Class Model{
        public int LocationId {get;set;}
        public int Occurences{get;set;}
        public IList<User> Users{get;set;}
    }

Initialize the container as a list of items.

var container = List<Model>();

Process you list of users.

foreach(var user in userList){
    var model = container.SingleOrDefault(x=> x.LocationId == user.LocationId);

    if(model != null){

       model.Users.Add(user);

    } else{
      model = new Model{
      model.Users = new List<User>.Add(user);
      model.LocationId = user.LocationId;
      container.Add(model)
    }
    model.Occruences ++;
}

}

Upvotes: 0

abatishchev
abatishchev

Reputation: 100248

using System.Linq;

var grouppingByLocation = users.GroupBy(u => u.LocationID);
foreach (var g in grouppingByLocation)
{
     Console.WriteLine("Location id: {0}", g.Key);
     foreach (var u in g)
     {
          Console.WriteLine("User id: {0}", u.ID);
     }
}

See Enumerable.GroupBy() for more details.

This is an Extension Method over IEnumerable<T> interface implemented by any built-in collection (such as Array T[], List<T>, Dictionary<K,V>, etc.) which accepts a lambda expression pointing to a property of class collection of which you're grouping by.

Upvotes: 2

Anri
Anri

Reputation: 6265

If you want to build the list looping through initial data, you can create object like this:

var list = new Dictionary<int, Tuple<int, List<int>>();

And fill it in the loop

if(list[locationID]==null) list[locationID] = Tuple.Create(0,new List<int>());
//..
list[locationId].Item1++;  // counter    
list[locationId].Item2.Add(userId); //list of users

Upvotes: 0

Related Questions