0

I have a list of objects List<People> person= new List<People>(); and each object (person) has some properties (such age, rank, etc).

I want to find persons with the same age and assign a random permutation to their rank.

For example: person[0].age=20; person[1].age=22; person[2].age=22; person[3].age=20; person[4].age=20;

Therefore, a feasible situation can be as

person[0].rank=3; person[1].rank=1; person[2].rank=2; person[3].rank=2; person[4].rank=1;

Dan Puzey
  • 33,626
  • 4
  • 73
  • 96
Amin
  • 127
  • 8
  • I want to find persons with the same age and assign a random permutation to their rank. – Amin Mar 10 '17 at 14:32

3 Answers3

0
var personsByAge = persons.GroupBy(person => person.age); 
foreach(var personAgeGroup in personsByAge) 
{
    var counter = 1;
    foreach(var person in personAgeGroup.Shuffle())
    {
        person.rank = counter;
        counter++;
    }
}

//Shuffling

public static class EnumerableExtensions
{
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
    {
        return source.Shuffle(new Random());
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (rng == null) throw new ArgumentNullException("rng");
        return source.ShuffleIterator(rng);
    }

    private static IEnumerable<T> ShuffleIterator<T>(
    this IEnumerable<T> source, Random rng)
    {
        var buffer = source.ToList();
        for (int i = 0; i < buffer.Count; i++)
        {
            int j = rng.Next(i, buffer.Count);
            yield return buffer[j];
            buffer[j] = buffer[i];
        }
    }
}

Credit to LukeH for the shuffle code.

Community
  • 1
  • 1
Timothy Stepanski
  • 1,186
  • 7
  • 21
0

Assuming we have a list

List<People> person = new List<People>();

Get the distinct ages and assign a specific rank value to each person sharing this age

var ages = person.Select(r => r.Age).Distinct();
foreach (int age in ages)
{
    int new_rank = new Random().Next(1, 5);
    person.ForEach(p => { if (p.Age == age) { p.Rank = new_rank; } });
}
Innat3
  • 3,561
  • 2
  • 11
  • 29
0

Here is another approach

void Main()
{
    IEnumerable<Person> people = new Person[] {
        new Person(1,20,"Bob"),
        new Person(1,22, "John"),
        new Person(1,22, "Paul"),
        new Person(1,20, "Kim"),
        new Person(1,20, "Justin")
    };

    List<Person> rankedPeople = new List<Person>();

    // just used for some sorting
    Random r = new Random((int)DateTime.Now.Ticks); 

    // Group by age and sort them randomly 
    foreach (var groupedPeople in people.GroupBy(p => p.Age) )
    {
        // Copy the persons from original list to a new one, at the sametime updating rank. 
        rankedPeople.AddRange(  groupedPeople.OrderBy(gp => r.Next()).Select( (val,index)  =>  new Person(index,val.Age, val.Name) ) );  
    }

    rankedPeople.ForEach(p => System.Console.WriteLine(p.ToString()));
}


public class Person
{
    public Person(int rank, int age, string name)
    {
        this.Rank = rank;
        this.Age = age;
        this.Name = name;
    }
    public int Rank { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }

    public override string ToString()
    {
        return string.Format($"{Rank} {Age} {Name}");
    }
}
MikNiller
  • 1,242
  • 11
  • 17