.net IEnumerable,其中所有元素都满足X且至少一个元素满足y

.net IEnumerable,其中所有元素都满足X且至少一个元素满足y,.net,linq,ienumerable,iteration,.net,Linq,Ienumerable,Iteration,我有2个IEnumerable。例如{0,0.1,0.5,1}和{a,b,c,d} 等长 域对象代码示例: public class Foo //does not implement IEnumerable because nothing outside of itself should treat it as such { private readonly decimal _a; private readonly decimal _b; private readonly decimal _c

我有2个
IEnumerable
。例如
{0,0.1,0.5,1}
{a,b,c,d}
等长

域对象代码示例:

public class Foo //does not implement IEnumerable because nothing outside of itself should treat it as such
{
 private readonly decimal _a;
private readonly decimal _b;
private readonly decimal _c;
//another class also has private readonly  decimal _d;

public decimal A {get{return _a;}}
//...
public decimal C {get{return _c;}}
}
我想定义
Foo1>Foo2

  • 如果全部满足
    =
    (如
    Foo1.A>=Foo2.A&&'..'Foo1.C>=Foo2.C
  • 至少有一个
    (如
    Foo1.B>Foo2.B
示例迭代代码:

//DRY violation, but probably the shortest route to the goal
private static IEnumerable<Func<Foo,decimal>> Accessors=
 new List{f=>f.A,f=>f.B,f=>f.C};

public static bool operator>(Foo foo1, Foo foo2)
{
  if (foo1==null||foo2==null)
    return false;
  bool foundGreater=false;
  foreach (var accessor in _Accessors)
  {
    if (accessor(foo1)<accessor(foo2))
      return false;
    if (foundGreater==false&&accessor(foo1)>accessor(foo2))
      foundGreater=true;
  }
  return foundGreater;
}
//干性违规,但可能是通往目标的最短路线
私有静态IEnumerable访问器=
新列表{f=>f.A,f=>f.B,f=>f.C};
公共静态布尔运算符>(Foo foo1,Foo foo2)
{
如果(foo1==null | | foo2==null)
返回false;
bool=false;
foreach(变量存取器在_存取器中)
{
if(存取器(foo1)存取器(foo2))
found=true;
}
回报率更高;
}
从学习的角度来看,涉及zip的信息和答案是受欢迎的,使用相同的不涉及反射的比较功能来解决可变属性长度的整个问题也是如此

然而,我目前正在使用LinqBridge在.NET2.0的范围内工作

我正在考虑以下内容来涵盖所有需要相同功能的类

  //Needs a better name for sure
  public static bool AllWithAny<T,TValue>(IEnumerable<Func<T,TValue>> accessors,T item1, T item2,
      Func<TValue,TValue,bool> shortCircuitBreak,Func<TValue,TValue,bool> atLeastOneCondition)
    {

      GuardStrategy.ThrowIfNull(accessors,"accessors");
      GuardStrategy.ThrowIfNull(item1, "item1");
      GuardStrategy.ThrowIfNull(item2, "item2");
      var foundOne=false;
      foreach(var accessor in accessors) 
      {
        var values=new {Value1=accessor(item1),Value2=accessor(item2)};
        if (shortCircuitBreak(values.Value1, values.Value2))
          return false;
        if(foundOne==false && atLeastOneCondition(values.Value1,values.Value2))
         {
          foundOne=true;
         }
      }
      return foundOne;

    }
//确实需要一个更好的名字
公共静态bool all with any(IEnumerable accessor,T item1,T item2,
Func短路中断,Func atLeastOneCondition)
{
安全策略。通过调用(访问器,“访问器”);
保障策略。全面(第1项,“第1项”);
保障策略。全面(第2项,“第2项”);
var-foundOne=false;
foreach(访问器中的var访问器)
{
var values=new{Value1=accessor(item1),Value2=accessor(item2)};
if(短路中断(values.Value1,values.Value2))
返回false;
if(foundOne==false&&atLeastOneCondition(values.Value1,values.Value2))
{
foundOne=true;
}
}
返回foundOne;
}
问题:

是否有一个现有的Linq关键字/运算符组合可以更优雅地完成这一切?
有没有一种更优雅/更简单的方法来进行这种比较,即更好的干法、更少的编码和更多的重用?

还没有经过测试,但稍加修改就可以了

public class Foo {
    public decimal A { get; set; }
    public decimal B { get; set; }
    public decimal C { get; set; }

    IEnumerable<decimal> Values {
        get { return new [] { A, B, C }; }
    }

    public static bool operator > (Foo x, Foo y)
    {
        var pairs = x.Values.Zip (y.Values,
            (xv, yv) => Tuple.Create (xv, yv));

        return pairs.All (pair => pair.Item1 >= pair.Item2)
            && pairs.Any (pair => pair.Item1 > pair.Item2);
    }
}
公共类Foo{
公共十进制A{get;set;}
公共十进制B{get;set;}
公共十进制C{get;set;}
IEnumerable值{
获取{returnnew[]{A,B,C};}
}
公共静态布尔运算符>(Foo x,Foo y)
{
变量对=x.Values.Zip(y.Values,
(xv,yv)=>Tuple.Create(xv,yv));
返回pairs.All(pair=>pair.Item1>=pair.Item2)
&&pairs.Any(pair=>pair.Item1>pair.Item2);
}
}
另外,我不太理解你的问题,所以我只是实现了你在开始时提出的问题。

这会奏效(使用@gaeron的想法公开
IEnumerable
的值以方便访问)


基本思想是,
foo1
要大于
foo2
,将
foo1.Values
中的每个元素与
foo2.Values
中的相应元素相减。Values必须>=0,并且必须至少有一个条目大于0。

如果所有值相等或。。。仅在属性C(或Z理论上)满足的任何条件不会完全消耗这两个序列,然后再次开始消耗它们以寻找任何更令人满意的?是的。你要在一个循环中做这个吗?这基本上是一样的,对吗?但是你的代码更干净,我喜欢。
public static bool operator >(Foo foo1, Foo foo2)
{
    if (foo1 == null || foo2 == null)
        return false;

    var zipSeq = foo1.Values.Zip(foo2.Values, (a, b) => a - b);
    bool isGreater = zipSeq.All(x => x >= 0) && zipSeq.Any(x => x > 0);

    return isGreater;
}