我想创建一个包含数组索引的数组。我们假设我有一个这样的数组:
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
我从查询中得到的结果如下:
这意味着地点1
,3, 4
(LengthUnit
= 2)和7
正忙(已经被占用)。所以,数组现在看起来像:
| T | 2 | T | T | 5 | 6 | T | 8 | 9 | 10 |
其中,T
代表。
如何使用查询结果创建两个整数数组,如下所示:
int[] taken = { 1, 3, 4, 7 };
int[] notTaken = { 2, 5, 6, 8, 9, 10 };
答案 0 :(得分:5)
Enumerable.Range
证明在这种情况下有用:
Dictionary<int, int> startAndLength = new Dictionary<int, int>()
{ { 1, 1 }, { 3, 2 }, { 7, 1 } };
int[] taken = startAndLength
.SelectMany(kvp => Enumerable.Range(kvp.Key, kvp.Value)).ToArray();
int[] notTaken = Enumerable.Range(0, 10).Except(taken).ToArray();
开始创建一组开始和长度,然后使用Enumerable.Range
确定所拍摄的项目。然后再次使用Enumerable.Range
确定不的项目。
答案 1 :(得分:2)
使用Enumerable.Range
创建所需的项目集合。然后使用Except
获取其他内容。
List<int> values = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
List<Tuple<int, int>> ranges = new List<Tuple<int, int>>
{
new Tuple<int, int>(1,1),
new Tuple<int, int>(3,2),
new Tuple<int, int>(7,1),
};
var t = ranges.SelectMany(range => Enumerable.Range(range.Item1, range.Item2)).ToList();
// Here I decide to use Intersect instead of just having t for the case
// where you requested a range that doesn't exist
var taken = values.Intersect(t).ToArray();
var notTaken = values.Except(taken).ToList();
如果您想要这些值并且不是顺序,就像在示例中那样:创建所有所需索引的集合,然后获取这些索引的所有项:
var indexes = ranges.SelectMany(range => Enumerable.Range(range.Item1, range.Item2)).Select(item => item - 1).ToList();
var taken = values.Where((item, index) => indexes.Contains(index)).ToList();
var notTaken = values.Where((item, index) => !indexes.Contains(index)).ToList();
答案 2 :(得分:1)
一点点Linq会让你走得很远:
public class QueryResult
{
public int StartUnit { get; set; }
public int LengthUnit { get; set; }
}
var input = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var queryResult = new QueryResult[]
{
new QueryResult { StartUnit = 1, LengthUnit = 1 },
new QueryResult { StartUnit = 3, LengthUnit = 2 },
new QueryResult { StartUnit = 7, LengthUnit = 1 },
};
var taken = new List<int>();
taken.AddRange(queryResult.SelectMany(q => (input.Skip(q.StartUnit - 1).Take(q.LengthUnit))));
Console.WriteLine("Taken: {0}", string.Join(",", taken));
var notTaken = input.Except(taken);
Console.WriteLine("Not taken: {0}", string.Join(",", notTaken));
使用SelectMany()
,Skip()
和Take()
,您可以选择要包含的范围。使用Except()
,您可以获取未拍摄的项目。
请注意,这会执行得非常糟糕,因为它会多次迭代集合。它还假设StartUnit
实际上表示输入集合中的(索引+ 1),而不是值。
如果您实际上不想查看输入数组,并且值始终是连续的(即输入中没有空洞),则可以使用Enumerable.Range()
生成请求的范围:
taken.AddRange(queryResult.SelectMany(q => Enumerable.Range(q.StartUnit, q.LengthUnit)));
生成要从Except()
排除的全部范围:
var notTaken = Enumerable.Range(1, 10).Except(taken);
当然,如果您希望输出实际上是数组,请在此处拨打ToArray()
。