score:7
The Order property should not be an integer but a decimal. You can easily change the value and then sort by it to retrieve the items in any arbitrary order. The new value is the midpoint between the preceding and following values.
P.S. Then you only have to change the Order property for the item(s) in the list you want to reposition.
score:1
If you can afford to I would number them with gaps in between:
a0.Order is 10
a1.Order is 20
a2.Order is 30
a3.Order is 40
This way you can simple reorder by picking a number within a gab.
a0.Order is 35
a1.Order is 20
a2.Order is 30
a3.Order is 40
After some iterations you may have no gabs left at some insertion point. With 100 items you can simple reset all the order numbers to have equal gabs again.
score:7
You could do something like this:
void MoveAndUpdateOrder(List<A> list, A item, int positionToInsert)
{
// Order elements
var ordered_list = list.OrderBy(a => a.Order).ToList();
// Remove and insert at the proper position
ordered_list.Remove(item);
ordered_list.Insert(positionToInsert, item);
// Update the Order properties according to it's current index
for ( int i = 0; i < ordered_list.Count; i++ )
ordered_list[i].Order = i;
}
And then call it like this:
var a0 = new A { Order = 0 };
var a1 = new A { Order = 1 };
var a2 = new A { Order = 2 };
var a3 = new A { Order = 3 };
var list = new List<A>
{
a0, a1, a2, a3
};
MoveAndUpdateOrder( list, a0, 2 );
score:3
We have to differentiate between moving an element upwards (to the end) or downwards (to the beginning of the list). Let's define two order numbers i
and k
where i < k
.
Move element i
upwards to k
:
The orders below i
and above k
are not affected.
The orders i+1 ... k
are decreased by one and i
becomes k
.
A moving = list.Where(a => a.Order == i);
foreach (A x in list.Where(a => a.Order > i && a.Order <= k)
{
x.Order--;
}
moving.Order = k;
Move element k
downwards to i
:
The orders below i
and above k
are not affected.
The orders i ... k-1
are increased by one and k
becomes i
.
A moving = list.Where(a => a.Order == k);
foreach (A x in list.Where(a => a.Order >= i && a.Order < k)
{
x.Order++;
}
moving.Order = i;
score:0
Could you just keep the items in a list and imply the Order
property from the physcial order of the items in the list?
Given an Item
class without an order property, like so:
class Item
{
public readonly string Value;
public Item(string value)
{
Value = value;
}
public override string ToString()
{
return Value;
}
}
You could write a simple collection class for Items
which has a Move()
method to let you move an item from one index to another:
class Items: IEnumerable<Item>
{
private readonly List<Item> _items = new List<Item>();
public void Add(Item item)
{
_items.Add(item);
}
public int Count
{
get { return _items.Count; }
}
public void Move(int oldIndex, int newIndex)
{
Item item = _items[oldIndex];
_items.RemoveAt(oldIndex);
_items.Insert(newIndex, item);
}
IEnumerator<Item> IEnumerable<Item>.GetEnumerator()
{
return _items.GetEnumerator();
}
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
You can use Items
like so:
var items = new Items
{
new Item("a0"),
new Item("a1"),
new Item("a2"),
new Item("a3")
};
// ...
items.Move(0, 2); // Move the item at index 0 to index 2.
Then when you need the Order
you can synthesize it from the list's physical order like so:
var orderedItems = items.Select((item, index) => new { Item = item, Order = index});
score:0
I wrote the algorithm for You, that uses sorting and LinkedList collection:
using System;
using System.Collections.Generic;
namespace OrderExample {
public class A {
public int Order { get; set; }
}
public class Program {
// Change order so that a is ordered between b and c.
public static void SetOrder(List<A> list, A a, A b, A c) {
list.Sort((x, y) => x.Order.CompareTo(y.Order));
var linkedList = new LinkedList<A>(list);
var bNode = linkedList.Find(b);
if (bNode != null) {
linkedList.Remove(a);
linkedList.AddAfter(bNode, a);
var i = 0;
foreach (var value in linkedList) {
value.Order = i++;
}
}
}
static void Main() {
var a0 = new A {Order = 0};
var a1 = new A {Order = 1};
var a2 = new A {Order = 2};
var a3 = new A {Order = 3};
var list = new List<A> {a0, a1, a2, a3};
SetOrder(list, a0, a2, a3);
foreach (var a in list) {
Console.Out.WriteLine(a.Order);
}
Console.ReadKey();
}
}
}
Source: stackoverflow.com
Related Articles
- Easiest Way to Reorder a sequence
- LINQ Source Code Available
- How does this linq code that splits a sequence work?
- .NET 4 Code Contracts: "requires unproven: source != null"
- Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed
- creating Linq to sqlite dbml from DbLinq source code
- source code for LINQ 101 samples
- List or Array of String Contain specific word in Html Source Code
- c# Linq or code to extract groups from a single list of source data
- Convert string[] to int[] in one line of code using LINQ
- Code equivalent to the 'let' keyword in chained LINQ extension method calls
- Sequence contains no elements?
- Value cannot be null. Parameter name: source
- How to take all but the last element in a sequence using LINQ?
- Sequence contains more than one element
- Sequence contains no matching element
- Determine if a sequence contains all elements of another sequence using Linq
- Linq code to select one item
- C# - code to order by a property using the property name as a string
- Favorite way to create an new IEnumerable<T> sequence from a single value?
- How do I find the text within a div in the source of a web page using C#
- Does Distinct() method keep original ordering of sequence intact?
- Roslyn failed to compile code
- Easiest way to Rotate a List in c#
- Entity-framework code is slow when using Include() many times
- The data source does not support server-side data paging
- How are people unit testing code that uses Linq to SQL
- LINQ: How to skip one then take the rest of a sequence
- Check for missing number in sequence
- Entity Framework, Code First and Full Text Search
- Extend DbFunctions EF6
- Linq.Dynamic Select custom column with operation
- Generating a query with related data and conditions using LINQ expressions
- How can I find the most items of a certain type in a List?
- Sum and GroupBy
- Moq setup not returning expected object, mismatched invocation
- LINQ expression String.Contains doesn't work
- Linq filter to avoid a loop
- Find an Object that contains a string in a list of strings using LINQ
- Can't verify method called inside Select() using Moq framework
- Querying using NULL on varchar column
- Help needed on linq query
- Filter linq list on property value
- LINQ Left Join 3 tables with OR operator
- how to get empty groups, lazily
- Linq Multiple Joins and Group By
- ReactiveUI "Compelling Example" search with Caliburn.Micro.ReactiveUI
- LINQ to Entities does not recognize the method 'System.String StringConvert(System.Nullable`1[System.Double])
- Using Lambda or Linq Get data based on child table
- How can I use Entity Framework on an object graph past a depth of 2 with MySQL Connector / NET?