Giu*_*adu 3 c# algorithm int list
我正在研究一种可以解决我遇到的问题的算法,但我发现自己有点卡住了。这是场景:
我有一个对象,其中包含一个名为 order 的变量。
public class Item
{
public int Order{get; set;};
public int ID{get; set;}; // not incremented can be any value!
}
Run Code Online (Sandbox Code Playgroud)
所以我有一个列表:
List<Item> list = new List<Item>().OrderBy((o) => o.Order);
Run Code Online (Sandbox Code Playgroud)
并且可以随时更改订单值。因此,如果我想更改第一个项目订单值,则所有其他订单值都应相应更新,以免重复。
for (int i = 0; i <= list .Count - 1; i++)
{
if (list [i].ID == inputID)
{
list [i].Order = inputNewPosition;
}
else
{
if (list [i].Order < inputNewPosition)
{
list [i].Order --;
}
else
{
list [i].Order ++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我将最后一个项目的顺序更改为第一个,这将失败,因为这会使第一个项目的顺序为 0!
任何人都可以帮忙吗?
谢谢
让我们看一下列表中元素的四种情况(在我们遍历它们时)。如果(为简洁起见)我们将old移动的项目的旧位置new作为其新位置,我们将在您的列表中为一个项目提供以下情况(将它们画在纸上以明确这一点)。
new和 < old:不要移动它new和 < old:向右移动new和 > old:向左移动new和 > old:不要移动它当我们开始枚举时,我们知道要移动的项目将在哪里结束(at new),但我们不知道它从哪里来(old)。然而,当我们从列表的开头开始枚举时,我们知道在每一步都必须在列表中更靠后,直到我们真正看到它!所以我们可以用一个标志(seen)来表示我们是否已经看到了它。所以seenfalse 意味着 <old而 true 意味着 >= old。
bool seen = false;
for (int i = 0; i < items.Length; i++)
{
if (items[i].ID == inputID)
{
items[i].Order = inputNewPosition;
seen = true;
}
}
Run Code Online (Sandbox Code Playgroud)
这个标志告诉我们当前项目是否 >= old。所以现在可以根据这些知识和上述规则开始分流。(所以new在上面的讨论中inputNewPosition,我们是在old用seen变量表示之前还是之后。)
bool seen;
for (int i = 0; i < items.Count; i++)
{
if (items[i].ID == inputID) // case 1
{
items[i].Order = inputNewPosition;
seen = true;
}
else if (seen) // cases 4 & 5
{
if (items[i].Order <= inputNewPosition) // case 4
{
items[i].Order--; // move it left
}
}
else // case 2 & 3
{
if (items[i].Order >= inputNewPosition) // case 3
{
items[i].Order++; // move it right
}
}
}
Run Code Online (Sandbox Code Playgroud)
说了这么多,在每次更改时对集合进行排序可能更简单。默认的排序算法应该非常简洁,几乎是排序的集合。