从源数组

时间:2016-08-22 09:02:00

标签: c# .net arrays

我想创建一个包含数组索引的数组。我们假设我有一个这样的数组:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

我从查询中得到的结果如下:

enter image description here

这意味着地点13, 4LengthUnit = 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 };

3 个答案:

答案 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()