2015-04-23 104 views
0

有没有办法用LINQ来选择具有快捷标准的特定数字。 喜欢这个: 我有1 to 10000的号码。 我的标准是(4012..4190|4229)4012 to 4190和数量4229间意取号:选择时间间隔linq

static int[] test(string criteria) 
    { 
     // criteria is 4012..4190|4229 
     // select numbers from lab where criteria is met 
     int[] lab = Enumerable.Range(0, 10000).ToArray(); 

     return lab; 
    } 
+3

你已经做了什么努力? – Andrey

回答

3

如果您criteria始终是一个string,你需要一些方法来分析它,Func<int, bool,但它不是LINQ特定。到底你需要这样的事:

Func<int, bool> predicate = Parse(criteria); 
return lab.Where(predicate).ToArray(); 

其中非常基本实现Parse可能如下:

public static Func<int, bool> Parse(string criteria) 
{ 
    var alternatives = criteria 
     .Split('|') 
     .Select<string, Func<int, bool>>(
      token => 
      { 
       if (token.Contains("..")) 
       { 
        var between = token.Split(new[] {".."}, StringSplitOptions.RemoveEmptyEntries); 
        int lo = int.Parse(between[0]); 
        int hi = int.Parse(between[1]); 
        return x => lo <= x && x <= hi; 
       } 
       else 
       { 
        int exact = int.Parse(token); 
        return x => x == exact; 
       } 
      }) 
     .ToArray(); 

    return x => alternatives.Any(alt => alt(x)); 
} 
+0

这是很棒的东西!奇迹般有效。非常感谢 – Gmorken

3

这应该足以为你的情况:

return lab.Where((int1) => (int1 >= 4012 && int1 <= 4190) || int1 == 4229).ToArray(); 

而且解析您的标准的快速方法是使用正则表达式:

Regex r = new Regex(@"\d+"); 
MatchCollection m = r.Matches(criteria); 
int start = int.Parse(m[0].Value); 
int end = int.Parse(m[1].Value); 
int specific = int.Parse(m[2].Value); 
return lab.Where((int1) => (int1 >= start && int1 <= end) || int1 == specific).ToArray(); 
1

可以连接两个序列

int[] lab = Enumerable.Range(4012, 4190-4012).Concat(Enumerable.Range(4229,1)).ToArray(); 

更新:

你需要解析第一个进入的标准

static int[] test(string criteria) 
    { 
     // criteria is 4012..4190|4229 
     // select numbers from lab where criteria is met 

     // assume you parsed your criteria to 2 dimentional array 
     // I used count for second part for convience 
     int[][] criteriaArray = { new int[]{ 4012, 50 }, new int[]{ 4229, 1 } }; 

     var seq = Enumerable.Range(criteriaArray[0][0], criteriaArray[0][1]); 

     for (int i = 1; i < criteriaArray.Length; i++) 
     { 
      int start = criteriaArray[i][0]; 
      int count = criteriaArray[i][1]; 
      seq = seq.Concat(Enumerable.Range(start, count)); 
     } 


     return seq.ToArray(); 
    } 
+0

顺便说一句,你需要解析你的标准,并取代各自的数字 – Orifjon

+0

伟大的工作,但问题是这样的标准可以看起来像这样不同: 4370 | 7010..7299 | 7331..7575 | 7691。 .7698 4480 | 7310 | 7610..7690 等等...如何解决这个问题?我如何解析标准? – Gmorken

+0

如果你解析条件数字对数组(开始,计数)或(开始,结束),你可以连接你的序列在循环 – Orifjon

0

,你可以: Flatten[{Range[4012, 4190], 4229}]

并以某种方式这也可以工作4012..4190|4229,但答案正是 - 从4012到4190和项目4229的项目列表。

Lambda只是模仿纯粹的功能。但是,除非你有免费的wolfram内核,否则使用这种方法可能不是最具成本效益的。但是,您不需要编写样板代码。