- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
更新:这是完整的代码https://dotnetfiddle.net/eAeWp5
这个比我想象的要难得多。在实际项目中,我需要更新一个包含列 Position
的数据库表(对于排序顺序),但所有方法获取的是一个列表,其中仅包含具有新位置的已更改对象。表和类是 WatchList
.
这里是:
public class WatchList : IEquatable<WatchList>
{
public WatchList(int id)
{
Id = id;
}
public int Id { get; }
public string Name { get; set; }
public int UserId { get; set; }
public int Position { get; set; }
public bool Equals(WatchList other)
{
if (other == null) return false;
if (ReferenceEquals(this, other)) return true;
return this.Id == other.Id;
}
public override bool Equals(object obj)
{
WatchList other = obj as WatchList;
return this.Equals(other);
}
public override int GetHashCode()
{
return this.Id;
}
public override string ToString()
{
return $"WatchListId:{Id} Name:{Name} UserId:{UserId} Position:{Position}";
}
}
所以 WatchListId
是主键,Position
我要更新的列。
考虑到此表包含以下观察列表:
WatchListId Position
1 1
2 2
3 3
4 4
5 5
用户想修改订单,拖拽,最后提交给服务器。客户将调用 UpdateWatchListsSort
列表仅包含用户移动的监视列表。
考虑用户移动
1 ---> 5
3 ---> 1
5 ---> 4
所以数据库中的新(正确)顺序是:
WatchListId Position
3 1
2 2
4 3
5 4
1 5
您注意到甚至一些其他观察列表也必须更新,因为如果它们的位置受到影响,则位置需要向上移动 1。这是它变得棘手。所有未移动到某个位置的项目应保持稳定的顺序(通过 Position
)。在这种情况下,ID=2 和 ID=4 应保持此顺序。
样本:
class Program
{
static void Main(string[] args)
{
var changedWatchLists = new List<WatchList>
{
new WatchList(1) {Position = 5}, new WatchList(3) {Position = 1}, new WatchList(5) {Position = 4}
};
WatchList.UpdateWatchListsSort("123", changedWatchLists);
}
}
我的方法是先加载完整的 List<WatchList>
(来自数据库),然后将其与传递的列表与新位置合并。这使得能够在之前验证输入并且应该使它更简单,因为所有都可以在内存中完成。
基本逻辑是Remove
都变了WatchLists
从完整列表然后Insert
它在所需的位置。
为了避免副作用,我只列举了新职位排序的变更列表。否则List.Insert
可以向上移动已经具有目标位置的项目。
但是,最后我仍然有一些项目在错误的位置,所以我被卡住了。
完整方法UpdateWatchListsSort
:
public static void UpdateWatchListsSort(string userId, List<WatchList> watchListsWithModifiedPosition)
{
List<WatchList> allUserWatchLists = GetWatchListsFromDb(userId);
// mapping WatchListId --> WatchList (from DB)
Dictionary<int, WatchList> dbWatchListIdLookup = allUserWatchLists.ToDictionary(w => w.Id);
if (watchListsWithModifiedPosition.Count == allUserWatchLists.Count)
allUserWatchLists = watchListsWithModifiedPosition;
else
{
// enumerate all modified WatchLists ordered by position ascending (to avoid side affects)
foreach (WatchList modified in watchListsWithModifiedPosition.OrderBy(w => w.Position))
{
WatchList dbWatchList = dbWatchListIdLookup[modified.Id];
int newIndex = modified.Position - 1;
int oldIndex = allUserWatchLists.IndexOf(dbWatchList); // might be at a different position meanwhile( != db-position )
allUserWatchLists.RemoveAt(oldIndex);
// if moved forwards index is index-1 because the watchlist was already removed at List.RemoveAt,
// if moved backwards index isn't affected
bool movedForwards = newIndex > oldIndex;
if (movedForwards)
newIndex--;
allUserWatchLists.Insert(newIndex, dbWatchList);
}
}
var changeInfos = allUserWatchLists
.Select((wl, index) => new { WatchList = wl, NewPosition = index + 1 })
.Where(x => x.WatchList.Position != x.NewPosition)
.ToList();
foreach (var change in changeInfos)
{
WatchList wl = change.WatchList;
wl.Position = change.NewPosition;
// check if the new position is equal to the position given as parameter
Debug.Assert(wl.Position == watchListsWithModifiedPosition
.Where(w => w.Id == wl.Id)
.Select(w => w.Position)
.DefaultIfEmpty(wl.Position)
.First());
}
// check if allUserWatchLists contains duplicate Positions which is invalid
Debug.Assert(allUserWatchLists
.Select(w => w.Position)
.Distinct().Count() == allUserWatchLists.Count);
// update changeInfos.Select(x => x.WatchList) via table-valued-parameter in DB (not related) .....
}
private static List<WatchList> GetWatchListsFromDb(string userId)
{
var allDbWatchLists = new List<WatchList>
{
new WatchList(1) {Position = 1}, new WatchList(2) {Position = 2}, new WatchList(3) {Position = 3},
new WatchList(4) {Position = 4}, new WatchList(5) {Position = 5}
};
return allDbWatchLists;
}
如果您执行此示例此 Debug.Assert
会失败:
// check if the new position is equal to the position given as parameter
Debug.Assert(wl.Position == watchListsWithModifiedPosition
.Where(w => w.Id == wl.Id)
.Select(w => w.Position)
.DefaultIfEmpty(wl.Position)
.First());
所以算法是错误的,因为 WatchList
新Position
不是所需的(作为参数给出)。
我希望你理解这个要求并看看我做错了什么。我怀疑这部分但不知道如何解决:
// if moved forwards index is index-1 because the watchlist was already removed at List.RemoveAt,
// if moved backwards index isn't affected
bool movedForwards = newIndex > oldIndex;
if (movedForwards)
newIndex--;
也许您有更好的方法,可读性很重要。
最佳答案
我建议使用插入排序算法原理。算法步骤为:
original
)和输入对象列表(input
)input
中original
中的所有对象。按 Position
字段排序其余部分。将这个新列表称为 ordered
ordered
的位置并将其放置在那里最后你会得到一个正确排序的对象列表,但是位置已经过时了。但是位置现在对应于对象在 ordered
列表中的索引,所以这很容易修复。
代码来说明我的意思。我对定义做了一些简化以使其简短:
class WatchList
{
public int WatchListId;
public int Position;
}
List<WatchList> original = new List<WatchList>
{
new WatchList{WatchListId=1, Position=1},
new WatchList{WatchListId=2, Position=2},
new WatchList{WatchListId=3, Position=3},
new WatchList{WatchListId=4, Position=4},
new WatchList{WatchListId=5, Position=5}
};
List<WatchList> input = new List<WatchList>
{
new WatchList{WatchListId=1, Position=5},
new WatchList{WatchListId=3, Position=1},
new WatchList{WatchListId=5, Position=4}
};
现在算法是这样的:
List<WatchList> ordered = original.Where(w => !input.Any(iw => iw.WatchListId == w.WatchListId)).OrderBy(w => w.Position).ToList();
foreach (var inputWatchlist in input)
{
int indexToInsert = 0;
while (indexToInsert < ordered.Count)
{
if (ordered[indexToInsert].Position <= inputWatchlist.Position)
{
indexToInsert++;
}
else
{
break;
}
}
ordered.Insert(indexToInsert, inputWatchlist);
}
这输出
foreach (var w in ordered)
{
Console.WriteLine("Id: " + w.WatchListId + " P: " + w.Position);
}
Id: 3 P: 1
Id: 2 P: 2
Id: 4 P: 4
Id: 5 P: 4
Id: 1 P: 5
样本 fiddle 链接:https://dotnetfiddle.net/7MtjVZ
如您所见,对象按预期顺序排列,但位置不合适。然而,现在更新位置是微不足道的。
关于c# - 如何根据仅包含已更改索引的列表修改列表索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40285006/
SO亲爱的 friend 们: 2014 年 3 月 18 日。我正在处理一种情况,在使用 ng-repeat 时,数组内的元素(我从 Json 字符串中获取)更改了原始顺序。 需要明确的是,数组中的
有很多问题询问如何在 JavaScript 单击处理程序中更改 div 的类,例如,此处:Change Div style onclick .我理解得很好(只需更改 .className),并且它有效
我从access导入了一个数据库到mysql,但其中一个表的列名“股数”带有空格,但我尝试更改、替换甚至删除列名,但失败了。任何人都可以帮助解决这一问题 String UpdateQuary = "U
我正在做一个随机的学校元素。 目前,我有一个包含两个 CSS 的页面。一种用于正常 View ,一种用于残障人士 View 。 此页面还包括两个按钮,它们将更改使用的样式表。 function c
我需要使用 javascript 更改 HTML 元素中的文本,但我不知道该怎么做。 ¿有什么帮助吗? 我把它定义成这样: Text I want to change. 我正在尝试这样做: docum
我在它自己的文件 nav_bar.shtml 中有一个主导航栏,每个其他页面都包含该导航栏。这个菜单栏是一个 jQuery 菜单栏(ApyCom 是销售这些导航栏的公司的名称)。导航栏上的元素如何确定
我正在摆弄我的代码,并开始想知道这个变化是否来自: if(array[index] == 0) 对此: if(!array[index] != 0) 可能会影响任何代码,或者它只是做同样的事情而我不需
我一直在想办法调整控制台窗口的大小。这是我正在使用的函数的代码: #include #include #define WIDTH 70 #define HEIGHT 35 HANDLE wHnd;
我有很多情况会导致相同的消息框警报。 有没有比做几个 if 语句更简单/更好的解决方案? PRODUCTS BOX1 BOX2 BOX3
我有一个包含这些元素的 XELEMENT B Bob Petier 19310227 1 我想像这样转换前缀。 B Bob Pet
我使用 MySQL 5.6 遇到了这种情况: 此查询有效并返回预期结果: select * from some_table where a = 'b' and metadata->>"$.countr
我想知道是否有人知道可以检测 R 中日期列格式的任何中断的包或函数,即检测日期向量格式更改的位置,例如: 11/2/90 12/2/90 . . . 15/Feb/1990 16/Feb/1990 .
我希望能够在小部件显示后更改 GtkButton 的标签 char *ButtonStance == "Connect"; GtkWidget *EntryButton = gtk_button_ne
我正在使用 Altera DE2 FPGA 开发板并尝试使用 SD 卡端口和音频线路输出。我正在使用 VHDL 和 C 进行编程,但由于缺乏经验/知识,我在 C 部分遇到了困难。 目前,我可以从 SD
注意到这个链接后: http://www.newscientist.com/blogs/nstv/2010/12/best-videos-of-2010-progress-bar-illusion.h
我想知道在某些情况下,即使剧本任务已成功执行并且 ok=2,ansible 也会显示“changed=0”。使用 Rest API 和 uri 模块时会发生这种情况。我试图找到解释但没有成功。谁能告诉
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: add buttons to push notification alert 是否可以在远程通知显示的警报框中指定有
当您的 TabBarController 中有超过 5 个 View Controller 时,系统会自动为您设置一个“更多” View 。是否可以更改此 View 中导航栏的颜色以匹配我正在使用的颜
如何更改.AndroidStudioBeta文件夹的位置,默认情况下,该文件夹位于Windows中的\ .. \ User \ .AndroidStudioBeta,而不会破坏任何内容? /编辑: 找
我目前正在尝试将更具功能性的编程风格应用于涉及低级(基于 LWJGL)GUI 开发的项目。显然,在这种情况下,需要携带很多状态,这在当前版本中是可变的。我的目标是最终拥有一个完全不可变的状态,以避免状
我是一名优秀的程序员,十分优秀!