我有一份ID列表。如何选择id在列表中的所有行并保留顺序?
这就是我所拥有的:
var ids = new int[]{5, 1, 8, 2, 3};
var items = Db.Items.Where(x => ids.Contains(x.Id));
但它不会保留订单。
我知道我可以根据ID对项目进行排序,但我希望O(n)复杂。
此问题类似于:Select multiple records based on list of Id's with linq,但我需要按顺序保留行
答案 0 :(得分:3)
我没有那么多的查询和数据库,但你只需要做C#技巧就可以很快完成这个任务
before(done => {
mongoose.connect('mongodb://localhost/test', { useMongoClient : true });
mongoose.Promise = global.Promise;
mongoose.connection
.once('open', () => done())
.on('error', err => console.err('Db connection error', err);
});
});
我无法告诉它如何被翻译成数据库查询
我还没有对其进行测试,但这里的版本没有var ids = new int[]{5, 1, 8, 2, 3};
var dict = ids.Select((id, i) => new { Index = i, Id = id })
.ToDictionary(x => x.Id, x => x.Index);
var items = Db.Items
.Where(x => ids.Contains(x.Id))
.OrderBy(x => dict[x.Id]);
,但空间效率较低(实际上可能更慢):
OrderBy
还有另一种方法 - 只需进行反向连接:
var ids = new int[]{5, 1, 8, 2, 3};
var temp = Db.Items
.Where(x => ids.Contains(x.Id))
.ToLookup(x => x.Id);
var tempList = new List<IGrouping<int, Item>>();
for(int i = 0; i < ids.Length; i++)
{
tempList.Add(temp[ids[i]]);
}
var items = tempList.SelectMany(x => x);
这将导致按ids
排序的查询答案 1 :(得分:1)
如何投影到中间类型以保留原始索引,构建联合以及对索引进行排序?
class ItemWithIndex
{
public int Index { get; set; }
public Item Item { get; set; }
}
class Item
{
public int Id { get; set; }
}
int[] ids = { 5, 1, 8, 2, 3 };
IQueryable<ItemWithIndex> query = null;
for(int index = 0; index < ids.Length; index++)
{
int currentIndex = index;
int currentId = ids[index];
IQueryable<ItemWithIndex> next = db.Items
.Where(i => i.Id == currentId)
.Select(i => new ItemWithIndex { Index = currentIndex, Item = i });
query = query == null ? next : query.Concat(next);
}
ItemWithIndex[] items = query
.OrderBy(i => i.Index)
.ToArray();
以下是生成的查询:
SELECT
[UnionAll4].[Id] AS [C1],
[UnionAll4].[C1] AS [C2],
[UnionAll4].[Id1] AS [C3]
FROM (SELECT
[Extent1].[Id] AS [Id],
@p__linq__1 AS [C1],
[Extent1].[Id] AS [Id1]
FROM [dbo].[Items] AS [Extent1]
WHERE [Extent1].[Id] = @p__linq__0
UNION ALL
SELECT
[Extent2].[Id] AS [Id],
@p__linq__3 AS [C1],
[Extent2].[Id] AS [Id1]
FROM [dbo].[Items] AS [Extent2]
WHERE [Extent2].[Id] = @p__linq__2
UNION ALL
SELECT
[Extent3].[Id] AS [Id],
@p__linq__5 AS [C1],
[Extent3].[Id] AS [Id1]
FROM [dbo].[Items] AS [Extent3]
WHERE [Extent3].[Id] = @p__linq__4
UNION ALL
SELECT
[Extent4].[Id] AS [Id],
@p__linq__7 AS [C1],
[Extent4].[Id] AS [Id1]
FROM [dbo].[Items] AS [Extent4]
WHERE [Extent4].[Id] = @p__linq__6
UNION ALL
SELECT
[Extent5].[Id] AS [Id],
@p__linq__9 AS [C1],
[Extent5].[Id] AS [Id1]
FROM [dbo].[Items] AS [Extent5]
WHERE [Extent5].[Id] = @p__linq__8) AS [UnionAll4]
答案 2 :(得分:1)
我会说,
1,您可以像以前一样获得这些物品:
var ids = new int[]{5, 1, 8, 2, 3};
var items = Db.Items.Where(x => ids.Contains(x.Id));
然后你可以做类似的事情:
var orderedItems = new int[ids.Length()] // sorry, I'm codign in SO edit, not sure on the syntax
foreach(id in items)
{
var position = Array.IndexOf(items, id)
orderedITems[position] = id;
}
那应该按照你的要求做(也可以简化为一行)。
我希望它有所帮助,
涓
答案 3 :(得分:0)
这是一个可能的解决方案:
var ids = new int[] {5, 1, 8, 2, 3};
var items = new List<Item>();
for (int i = 0; i < ids.Length; i++)
{
items.Add(Db.Items.Find(ids[i]));
}
然而,它执行N个查询,因此应该有更好的方法。