Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用LINQ将对象分为两组_C#_Arrays_Linq_Group By - Fatal编程技术网

C# 如何使用LINQ将对象分为两组

C# 如何使用LINQ将对象分为两组,c#,arrays,linq,group-by,C#,Arrays,Linq,Group By,假设我有类发票: public class Invoice { public int PartNumber { get; set; } public string PartDescription { get; set; } public int Quantity { get; set; } public decimal Price { get; set; } } 然后在变量arrayOfInvoices中有一个对象数组 如果我必须将发票分为两组—单价低于1

假设我有类发票:

public class Invoice
{
    public int PartNumber { get; set; }

    public string PartDescription { get; set; }

    public int Quantity { get; set; }

    public decimal Price { get; set; }
}
然后在变量arrayOfInvoices中有一个对象数组


如果我必须将发票分为两组—单价低于12的发票和单价高于或等于12的发票,并按价格的升序显示每组发票的详细信息,我该怎么做?

您可以简单地执行以下操作:

var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by inv.Price < 12;
var priceBoundaries = new[] { 12m, 20m, Decimal.MaxValue }; // Note the addition of MaxValue
var i = 0;
var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by (inv.Price < priceBoundaries[i] ? i : ++i);
或者使用副作用,比如:

var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by inv.Price < 12;
var priceBoundaries = new[] { 12m, 20m, Decimal.MaxValue }; // Note the addition of MaxValue
var i = 0;
var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by (inv.Price < priceBoundaries[i] ? i : ++i);
var pricebounders=new[]{12m,20m,Decimal.MaxValue};//注意MaxValue的添加
var i=0;
风险值结果=
来自arrayOfInvoices中的inv
按库存价格订购
按组合存货(存货价格<价格边界[i]?i:+i);

这通常是不好的做法,但应该比上面的BinarySearch方法执行得更好。

您可以简单地执行以下操作:

var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by inv.Price < 12;
var priceBoundaries = new[] { 12m, 20m, Decimal.MaxValue }; // Note the addition of MaxValue
var i = 0;
var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by (inv.Price < priceBoundaries[i] ? i : ++i);
或者使用副作用,比如:

var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by inv.Price < 12;
var priceBoundaries = new[] { 12m, 20m, Decimal.MaxValue }; // Note the addition of MaxValue
var i = 0;
var results = 
    from inv in arrayOfInvoices 
    orderby inv.Price
    group inv by (inv.Price < priceBoundaries[i] ? i : ++i);
var pricebounders=new[]{12m,20m,Decimal.MaxValue};//注意MaxValue的添加
var i=0;
风险值结果=
来自arrayOfInvoices中的inv
按库存价格订购
按组合存货(存货价格<价格边界[i]?i:+i);

这通常是一种不好的做法,但应该比上面的BinarySearch方法执行得更好。

如果使用组函数很麻烦(有时会让人讨厌),那么您也可以使用“Where”

var发票=新列表();
var group1=发票。其中(i=>i.Price i.Price).ToList();
var group2=invoices.Where(i=>i.Price>=12).Orderby(i=>i.Price.ToList();

如果使用组功能是一种痛苦(有时会让人讨厌),那么您也可以使用“Where”

var发票=新列表();
var group1=发票。其中(i=>i.Price i.Price).ToList();
var group2=invoices.Where(i=>i.Price>=12).Orderby(i=>i.Price.ToList();

您可以将范围的概念封装在类中:

private class PriceRange<T> : IEquatable<PriceRange<T>>
{
    public T Min { get; set; }
    public T Max { get; set; }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 31 + Min.GetHashCode();
            hash = hash * 31 + Max.GetHashCode();
            return hash;
        }
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as PriceRange<T>);
    }

    public bool Equals(PriceRange<T> other)
    {
        if (other == null) return false;

        if (!Min.Equals(other.Min)) return false;
        if (!Max.Equals(other.Max)) return false;

        return true;
    }
}
私有类价格范围:IEquatable
{
公共T Min{get;set;}
公共T Max{get;set;}
公共覆盖int GetHashCode()
{
未经检查
{
int hash=17;
hash=hash*31+Min.GetHashCode();
hash=hash*31+Max.GetHashCode();
返回散列;
}
}
公共覆盖布尔等于(对象对象对象)
{
收益等于(obj作为价格范围);
}
公共布尔等于(价格范围其他)
{
if(other==null)返回false;
如果(!Min.Equals(other.Min))返回false;
如果(!Max.Equals(other.Max))返回false;
返回true;
}
}
然后使用映射功能将每张发票的价格映射到适当的范围:

private class PriceRangeFactory<T>
{
    public PriceRangeFactory(T[] rangeCutoffs)
    {
        _RangeCutoffs = rangeCutoffs;
    }

    private T[] _RangeCutoffs;

    public PriceRange<T> Map(T price)
    {
        var index = Array.BinarySearch(_RangeCutoffs, price);
        // Assume that the _RangeCutoffs that we have fully cover all possible values for T.
        if (index < 0) index = ~index;

        return new PriceRange<T>() { Min = _RangeCutoffs[index - 1], Max = _RangeCutoffs[index] };
    }
}
私有类PriceRangeFactory
{
公共价格范围工厂(T[]范围截止值)
{
_范围截止=范围截止;
}
私人T[]_范围截止值;
公共价格范围图(T价格)
{
var index=Array.BinarySearch(_RangeCutoffs,price);
//假设我们的_范围截止值完全覆盖了T的所有可能值。
如果(索引<0)索引=~index;
返回新的pricelange(){Min=_RangeCutoffs[index-1],Max=_RangeCutoffs[index]};
}
}
然后将GroupBy与该映射函数一起使用:

var rangeFactory = new PriceRangeFactory<decimal>(new decimal[] { decimal.MinValue, 12, 20, decimal.MaxValue });
var grouped = foos.GroupBy(a => rangeFactory.Map(a.Price));
var rangeFactory=new PriceRangeFactory(new decimal[]{decimal.MinValue,12,20,decimal.MaxValue});
var group=foos.GroupBy(a=>rangeFactory.Map(a.Price));
您将获得一个iGroup列表,每个iGroup都由指定的范围设置关键帧,并附着适合该范围的适当对象

现在,显然上面的代码并不完全是生产级的,但它应该足以让您开始。至于为什么它没有达到生产水平:

  • 没有检查来断言提供给PriceRangeFactory的范围实际上完全覆盖了所有可能的值

  • 它总是假设范围被描述为>X,并且您可以将范围的概念封装在一个类中:

    private class PriceRange<T> : IEquatable<PriceRange<T>>
    {
        public T Min { get; set; }
        public T Max { get; set; }
    
        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 31 + Min.GetHashCode();
                hash = hash * 31 + Max.GetHashCode();
                return hash;
            }
        }
    
        public override bool Equals(object obj)
        {
            return Equals(obj as PriceRange<T>);
        }
    
        public bool Equals(PriceRange<T> other)
        {
            if (other == null) return false;
    
            if (!Min.Equals(other.Min)) return false;
            if (!Max.Equals(other.Max)) return false;
    
            return true;
        }
    }
    
    私有类价格范围:IEquatable
    {
    公共T Min{get;set;}
    公共T Max{get;set;}
    公共覆盖int GetHashCode()
    {
    未经检查
    {
    int hash=17;
    hash=hash*31+Min.GetHashCode();
    hash=hash*31+Max.GetHashCode();
    返回散列;
    }
    }
    公共覆盖布尔等于(对象对象对象)
    {
    收益等于(obj作为价格范围);
    }
    公共布尔等于(价格范围其他)
    {
    if(other==null)返回false;
    如果(!Min.Equals(other.Min))返回false;
    如果(!Max.Equals(other.Max))返回false;
    返回true;
    }
    }
    
    然后使用映射功能将每张发票的价格映射到适当的范围:

    private class PriceRangeFactory<T>
    {
        public PriceRangeFactory(T[] rangeCutoffs)
        {
            _RangeCutoffs = rangeCutoffs;
        }
    
        private T[] _RangeCutoffs;
    
        public PriceRange<T> Map(T price)
        {
            var index = Array.BinarySearch(_RangeCutoffs, price);
            // Assume that the _RangeCutoffs that we have fully cover all possible values for T.
            if (index < 0) index = ~index;
    
            return new PriceRange<T>() { Min = _RangeCutoffs[index - 1], Max = _RangeCutoffs[index] };
        }
    }
    
    私有类PriceRangeFactory
    {
    公共价格范围工厂(T[]范围截止值)
    {
    _范围截止=范围截止;
    }
    私人T[]_范围截止值;
    公共价格范围图(T价格)
    {
    var index=Array.BinarySearch(_RangeCutoffs,price);
    //假设我们的_范围截止值完全覆盖了T的所有可能值。
    如果(索引<0)索引=~index;
    返回新的pricelange(){Min=_RangeCutoffs[index-1],Max=_RangeCutoffs[index]};
    }
    }
    
    然后将GroupBy与该映射函数一起使用:

    var rangeFactory = new PriceRangeFactory<decimal>(new decimal[] { decimal.MinValue, 12, 20, decimal.MaxValue });
    var grouped = foos.GroupBy(a => rangeFactory.Map(a.Price));
    
    var rangeFactory=new PriceRangeFactory(new decimal[]{decimal.MinValue,12,20,decimal.MaxValue});
    var group=foos.GroupBy(a=>rangeFactory.Map(a.Price));
    
    您将获得一个iGroup列表,每个iGroup都由指定的范围设置关键帧,并附着适合该范围的适当对象

    现在,显然上面的代码并不完全是生产级的,但它应该足以让您开始。至于为什么它没有达到生产水平:

    • 没有检查来断言提供给PriceRangeFactory的范围实际上完全覆盖了所有可能的值
    • 它总是假定范围被描述为>X,您是否尝试过任何方法