Mookie
Mookie

Reputation: 35

List Renumbering duplicates c#

Im sure im not the first person to have this happen but ive tried from several different angles to resolve this and im having the same problem

I am retrieving items from a database, and i only want the last item for each position.

class Item {
  public bool is_scheduled {get;set;}
  public int round{get;set;}
  public int round_position {get;set;}

  [NotMapped]
  public int position {get;set;}
  public int ItemsRequired{get;set;}
}

if the ItemsRequired is greater than 1, then i need to add copies of the same item to the list.

after ive created the copy, I am then trying to renumber the item, which seems to work properly.

When i check the list as a whole, i have duplicates of the numbers though.

using (var context = new DBContext)
{
    var items = context.Items
   .Where(o => o.round == round && o.is_scheduled == false)
   .GroupBy(o => o.round_position)
   .ToList()
   .Select(GetLastItem)
   .ToList();

    foreach (var item in items)
    {
        Trace.WriteLine($"{item.position}");
    }
    return ParseItems(items);
}


private static List<Item> ParseItems(List<Item> items)
{
    var result = new List<Item>();

    var idx = 0;
    foreach (var item in items)
    {
        var carries = item.ItemsRequired.GetValueOrDefault();

        if (carries == 1)
        {
            idx = idx + 1;
            item.position = idx;
            Trace.WriteLine($"pos:{item.position}");
            result.Add(item);
        }
        else
        {
            for (var i = 0; i < carries; i++)
            {
                idx = idx + 1;
                item.position = idx;
                Trace.WriteLine($"pos:{item.position}");

                result.Add(item);

            }
        }
    }
    foreach (var r in result)
        Trace.WriteLine(r.position);
    return result;
}

private static Item GetLastItem(IGrouping<int?, Item> arg)
{
    var items = arg
        .OrderBy(o => o.date_created)
        .ToList();

    var last = items.Last();
    return last;
}

So if i were to take the items and assign a position as such.

items = items.Select((item,idx)=>{
var clone = item;
clone.position=idx;
return clone;}).ToList();

// Print items
foreach(var item in items)
Trace.WriteLine(item.position);

this currently shows duplicates of numbers in the output window.

Upvotes: 0

Views: 189

Answers (4)

Mookie
Mookie

Reputation: 35

I found the answer on my own, but i could really use help understanding why.

if i take

// Wrong
items.Select((item,i)=>{
item.position=i;
return item;
}).ToList();

foreach(var item in items)
Trace.WriteLine(item.position);

// This seems to work
items.Select((item,i)=>{
var result = new Item{position=i};
return result;
}).ToList();

foreach(var item in items)
Trace.WriteLine(item.position);

Upvotes: 0

Scrobi
Scrobi

Reputation: 1200

The inner for loop you have will be actually updating the same item over and over again as it is a reference type. You will instead need to create a new instance on Item.

...
else
{
    for (var i = 0; i<carries; i++)
    {
        idx = idx + 1;
        var itemClone = new Item();
        itemClone.position = idx
        itemClone.is_scheduled = item.is_scheduled;
        //...set other itemClone property values

        Trace.WriteLine($"pos:{itemClone.position}");

        result.Add(itemClone);

    }
}
...

Upvotes: 1

bslein
bslein

Reputation: 332

using(var context = new DBContext)
{
  var items = context.Items
  .Where(o => o.round == round && o.is_scheduled == false)
  .GroupBy(o=>o.round_position)
  .Select(x => new {Roundposition = x.Key, Item = x.LastOrDefault()})                    
  .ToList();
}

Upvotes: 0

jdweng
jdweng

Reputation: 34427

A group create a two dimension array. The long item (key) is the group and the short item is each item in the long array. So you need to use a select to enumerate through the keys and get last item of each key. Try following :

using(var context = new DBContext){
  .Where(o => o.round == round && o.is_scheduled == false)
  .GroupBy(o=>o.round_position)
  .Select(x => x.LastOrDefault())                    
  .ToList();

}

Upvotes: 0

Related Questions