1

The struct below consists of three variables, bool visible, int id, and int order.

List<Data.myStruct> itemList = new List<Data.myStruct>();

Then I add four items to the list

itemList.Add(new Data.myStruct(false, 1, 0));
itemList.Add(new Data.myStruct(false, 2, 0));
itemList.Add(new Data.myStruct(false, 3, 0));
itemList.Add(new Data.myStruct(false, 4, 0));

I can make a function to set the visibility of a given id to true.

public void setVisible(int id) {
    for(int i = 0; i < itemList.Count; i++)
    {
        if(id == itemList[i].id)
        {
            itemList[i] = new Data.myStruct(true, itemList[i].id, itemList[i].order);
        }
    }
}

My question would be this, How would I be able to set the order of each item in the itemList when bool visible = true based on when setVisible(int id) is called. So if setVisible(1) is called before setVisible(2) then the order of the second one would be greater than the first one, or vice versa.

For Example,

setVisible(1);
setVisible(2);

Result:

itemList[0].visible = true, itemList[0].id = 1, itemList[0].order = 1
itemList[1].visible = true, itemList[1].id = 2, itemList[1].order = 2
itemList[2].visible = false, itemList[2].id = 3, itemList[2].order = 0
itemList[3].visible = false, itemList[3].id = 4, itemList[3].order = 0

And if I were to change the visibility to false on one of them, How might I change the order to fill in the gap. Can this be done using linq?

Edit:

How would I be able to loop through the list by order of highest order value?

Tree Wood
  • 41
  • 10
  • I'm having a hard time understanding your question.. Are you trying to sort the list? – default Mar 05 '15 at 23:26
  • @Default Yes I am, but basing it off the order variable, and whether or not the visible variable is true. – Tree Wood Mar 05 '15 at 23:27
  • Looping through the list can be done via `OrderBy` and `ThenBy`. But I'm not sure how to apply it to your question. – default Mar 05 '15 at 23:27
  • @Default I suppose that would answer my last question. But the `order` of the items would be set whenever I use the `setVisible` function. Which is the other half of the question. – Tree Wood Mar 05 '15 at 23:32
  • 1
    May I suggest to use `class` instead of `struct` so that you don't have to recreate the item? Then you would be able to change the properties directly. Or are you locked to struct? – default Mar 05 '15 at 23:34
  • So you're creating a whole new object instead of just changing the visible member to true? If (id == itemList[i].id) itemList[i].visible = true; should do the trick. – Mihai Caracostea Mar 05 '15 at 23:36
  • @Default I'm locked to struct. – Tree Wood Mar 05 '15 at 23:37
  • *Something* is going to need to track the state of your items. The structs can't know what their order should be relative to each other: I recommend you create something that keeps track of in what order each struct has its visibility set, and then run through the list setting their order appropriately. – Dan J Mar 05 '15 at 23:41
  • @MihaiCaracostea I don't think that works, I just get an error when I use that way. – Tree Wood Mar 05 '15 at 23:41
  • How come it doesn't work? What error are you getting? – Mihai Caracostea Mar 05 '15 at 23:43
  • @MihaiCaracostea Cannot modify the return value of ... because it is not a variable – Tree Wood Mar 05 '15 at 23:43
  • Perhaps your fields have getters and no setters in place? – Mihai Caracostea Mar 05 '15 at 23:53
  • gotta go... but maybe this is what you're after: https://dotnetfiddle.net/npEKFx – default Mar 05 '15 at 23:56
  • @MihaiCaracostea No, they all have public { get; set; } – Tree Wood Mar 05 '15 at 23:56
  • Actually, here's what's happening https://msdn.microsoft.com/en-us/library/wydkhw2c.aspx It's all because how value types are stored in collections. – Mihai Caracostea Mar 05 '15 at 23:56
  • the reason for the error is explained here: http://stackoverflow.com/questions/1747654/cannot-modify-the-return-value-error-c-sharp – default Mar 05 '15 at 23:57
  • @Default Yes that's what I'm after, I think RagtimeWilly's answer might work as well but I haven't tested it yet. – Tree Wood Mar 05 '15 at 23:58
  • You need to do Data.myStruct temp = itemList[i]; temp.visible = true; itemList[i] = temp; – Mihai Caracostea Mar 05 '15 at 23:59
  • Is it ever possible to have a struct with `visible == true` and `order == 0`? Same question with `visible == false` and `order != 0`? – Dialecticus Mar 05 '15 at 23:59
  • @Dialecticus Well if it's not visible then it should be 0, and if it is visible then it shouldn't be 0. If it was visible and 0, then it would just be at the bottom of the order. – Tree Wood Mar 06 '15 at 00:01
  • What should happen with `order` of all list items if we call `setVisible` on item that is already visible? Same question with `setInvisible` and `visible == false`? – Dialecticus Mar 06 '15 at 00:03
  • @Dialecticus Well if an Item that is already visible is called again in setVisible then that item would jump to the highest order and if you're setting something invisible then it would always go to the order of 0. – Tree Wood Mar 06 '15 at 00:07
  • Also, I recommend you put a break; at the end of the if block so once you find your item, you don't iterate through the rest. Assuming id is unique, of course... – Mihai Caracostea Mar 06 '15 at 00:09
  • Just to make sure if I call `setVisible(x)` twice on invisible item then first time item gets `order == 1`, but second time it gets `order == n`, where `n` is number of visible items. Is this correct? – Dialecticus Mar 06 '15 at 00:15
  • @Dialecticus If you setVisible(x) then first time would be n(number of visible items) and second time would be n(number of visible items). So when you call setVisible() on any ID then that would be the highest in the order. – Tree Wood Mar 06 '15 at 00:18
  • 1
    But in your example the result is different from what you just described. – Dialecticus Mar 06 '15 at 00:19
  • @Dialecticus You are absolutely right and that's my fault, I didn't see that, my Example is incorrect, i'll fix it. – Tree Wood Mar 06 '15 at 00:20

2 Answers2

1

Are you just looking for a function to calculate the next order when setting visible to true.

Something along the lines of:

 public void setVisible(int id, List<Data.myStruct> itemList)
 {
     Func<List<Data.myStruct>, int> getNextOrder = list =>
     {
         if (itemList.Any(item => item.order > 0))
             return itemList.Max(item => item.order) - 1;

         return itemList.Count - 1;
     }; 

     for (int i = 0; i < itemList.Count; i++)
     {
         if (id == itemList[i].id && !itemList[i].visible)
         {
             itemList[i] = new Data.myStruct(true, itemList[i].id, getNextOrder(itemList));
         }
     }
 }

You also mentioned if you could use LINQ to update orders. LINQ should only ever be used for querying, so you should never use it to mutate the state of objects.

The above code obviously only accounts for setting visibility to true. If you need to set the visibilty of an item to false you should use a foreach loop to update the other orders afterwards.

EDIT:

Based on the revision to your question, the below code will set the visible item to the highest order and then re-order the other items:

public static void setVisible(int id, List<Data.myStruct> itemList)
{
    int previousOrder = int.MinValue;

    for (int i = 0; i < itemList.Count; i++)
    {
        if (id == itemList[i].id)
        {
            previousOrder = itemList[i].order;
            itemList[i] = new Data.myStruct(true, itemList[i].id, itemList.Count - 1);
        }
    }

    if (previousOrder == int.MinValue)
        return;

    for (int i = 0; i < itemList.Count; i++)
    {
        if (itemList[i].id != id && itemList[i].order > 0 && itemList[i].order >= previousOrder)
        {
            var order = itemList[i].order - 1;
            itemList[i] = new Data.myStruct(true, itemList[i].id, order);
        }
    }
}

To output values to console:

foreach (var item in itemList.OrderByDescending(i => i.order))
{
    Console.WriteLine(string.Format("{0} - {1} - {2}", item.id, item.visible, item.order));
}
RagtimeWilly
  • 5,265
  • 3
  • 25
  • 41
  • If I were to type setVisible(1) twice in a row, then instead of it outputting the order with 3, it would move it down to 2, if I call a setVisible() twice i'd like it to stay at the highest order. Sorry for not being clear with that. – Tree Wood Mar 06 '15 at 00:09
  • Added another version of function to answer revised question – RagtimeWilly Mar 06 '15 at 00:39
  • --itemList[i].order will return with an error, since were using structs you cannot modify the value because it's not a variable. Instead would itemList[i].order - 1 be a solution? – Tree Wood Mar 06 '15 at 00:41
  • If i were to put the into a console application, how could I be able to write them in order? I tried using the OrderByDescending() and ThenByDescending() but i'm having problems. – Tree Wood Mar 06 '15 at 00:45
  • If you just want to order by descending use `itemList.OrderByDescending(i => i.Order);` (See edit to answer) – RagtimeWilly Mar 06 '15 at 00:47
  • But how can I get the Console to write the IDs in the order of that statement. – Tree Wood Mar 06 '15 at 00:49
0

Beside your list, you can store another variable, say int currentOrder=0; And every time you do a setVisible call, set the order of that particular item to

++currentOrder

Can't post fancy code because I'm on the Android app.

Mihai Caracostea
  • 8,336
  • 4
  • 27
  • 46