0

我需要根据其中一个属性订购对象列表。我找到了各种答案,但没有一个按我需要的方式排序。我试图排序的属性称为“DrawingName”。我需要按如下顺序排列列表: "411000A","411000B","411000C","411000D","411000A","411000B","411000C","411000D"

相反,我得到: "411000A","411000A","411000B","411000B","411000C","411000C","411000D","411000D"

当我使用以下代码时。

List<DrawingData> _DrawingList = new List<DrawingData>();

_DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });        
_DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });

_DrawingList.OrderBy(dn => dn.DrawingName);

var _DrawingListInOrder = _DrawingList.OrderBy(dwg => dwg.DrawingName);
4

8 回答 8

3

做一次并计算DrawingName到目前为止每个的出现次数:

411000D 0x
411000D 1x
411000A 0x
411000A 1x
411000C 0x
411000C 1x
411000D 2x
411000B 0x
411000B 1x

然后,您可以按出现次数和字母顺序对它们进行排序。

411000A 0x
411000B 0x
411000C 0x
411000D 0x
411000A 1x
411000B 1x
411000C 1x
411000D 1x
411000D 2x
于 2013-10-04T13:26:07.523 回答
2

并不是说这是最有效的方法,但它确实有效:

List<DrawingData> _DrawingList = new List<DrawingData>();

_DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });
_DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });

var _WithIndex = _DrawingList.Select(x => new { DrawingData = x, Index = _DrawingList.Where(y => y.DrawingName == x.DrawingName).ToList().IndexOf(x) });
var _FinalOrder = _WithIndex.OrderBy(x => x.Index).ThenBy(x => x.DrawingData.DrawingName).Select(x => x.DrawingData);

Console.WriteLine("Final Sort:");
Console.WriteLine(string.Join("\n", _FinalOrder));

Console.ReadLine();

获取每个重复项的索引,然后对该索引进行排序,然后是名称。

让它变得简单了一些。可以是单个 LINQ 语句:

var _FinalOrder = _DrawingList
    .Select(x => new
        {
            DrawingData = x,
            Index = _DrawingList.Where(y => y.DrawingName == x.DrawingName)
                                .ToList()
                                .IndexOf(x)
        })
    .OrderBy(x => x.Index)
    .ThenBy(x => x.DrawingData.DrawingName)
    .Select(x => x.DrawingData);
于 2013-10-04T13:30:27.933 回答
0

假设这用于相对少量的数据,以下伪代码可能满足您的需求:

Take the list L of things to sort
Sort L normally (AABBCCDD order)
Create an empty list L2 and an empty set S
While L still has elements:
    Iterate over L
        If current element E is in S, ignore it
        Otherwise, add E to S, add it to the end of L2 and remove it from L
    Clear S

在此之后,L2应该有一个 ABCDABCD 顺序的元素。

于 2013-10-04T13:26:16.527 回答
0

试试这个:

using System;
using System.Collections.Generic;
using System.Linq;

class DrawingData {
    public string DrawingName{get;set;} 
    public int DrawingQty {get;set;}
}

class DrawingDataComparer : IEqualityComparer<DrawingData>
{

    public bool Equals(DrawingData d1, DrawingData d2)
    {
        return d1.DrawingName.Equals(d2.DrawingName);
    }


    public int GetHashCode(DrawingData d)
    {
        return d.DrawingName.GetHashCode();
    }

}

public class Test
{
    public static void Main()
    {
        List<DrawingData> _DrawingList = new List<DrawingData>();
        _DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000D", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000A", DrawingQty = 1 });        
        _DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000C", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });
        _DrawingList.Add(new DrawingData() { DrawingName = "411000B", DrawingQty = 1 });

        _DrawingList = _DrawingList.OrderBy(c => c.DrawingName).ToList();
        var distinct = _DrawingList.Distinct(new DrawingDataComparer());
        var organized = distinct.Concat(_DrawingList.Except(distinct));
        foreach(DrawingData dd in organized)
            Console.WriteLine(dd.DrawingName);
    }
}
于 2013-10-04T13:29:23.400 回答
0

根据我对要求的了解,您需要订购每个独特的集合。所以,拿一个独特的套装,订购它,并保留它。然后删除你刚刚使用的那些,然后再做一次。继续前进,直到您没有更多独特的套装可供订购。

List<DrawingData> ordered = new List<DrawingData>();
while (_DrawingList.Any())
{
    var temp = _DrawingList.Distinct().OrderBy(dd => dd.DrawingName, StringComparer.CurrentCultureIgnoreCase);
    ordered.AddRange(temp);
    foreach (var remove in temp)
    {
        _DrawingList.Remove(remove);
    }
}
_DrawingList = ordered;

为了使它起作用,我必须覆盖Equalsand GetHashCodein DrawingData

public override bool Equals(object obj)
{
    if (!(obj is DrawingData))
    {
        return base.Equals(obj);
    }
    else
    {
        return this.DrawingName.Equals((obj as DrawingData).DrawingName, StringComparison.OrdinalIgnoreCase);
    }
}

public override int GetHashCode()
{
    return DrawingName.GetHashCode();
}
于 2013-10-04T13:35:14.453 回答
0

假设您要将重复项拆分为单独的列表,则:

首先创建一个用于比较DrawingData对象的小类:

sealed class Comparer: IComparer<DrawingData>
{
    public int Compare(DrawingData x, DrawingData y)
    {
        // NOTE: Assumes DrawingName, x and y are never null.
        return x.DrawingName.CompareTo(y.DrawingName);
    }
}

然后假设您有一个填充列表,如示例中所示List<DrawingData> _DrawingList,拆分重复的项目,以便您有两个单独的列表:

var list1 = new SortedSet<DrawingData>(new Comparer());
var list2 = new SortedSet<DrawingData>(new Comparer());

foreach (var drawing in _DrawingList)
    if (!list1.Add(drawing))
        list2.Add(drawing);

如果需要,然后将 list1 和 list2 转换为实际列表:

var l1 = list1.ToList();
var l2 = list2.ToList();
于 2013-10-04T13:43:40.830 回答
0

您正在寻找一个分组,然后是一个转置:

string[] data = 
{
    "411000D", 
    "411000D", 
    "411000A",
    "411000A",        
    "411000C",
    "411000C",
    "411000B",
    "411000B"
};

var grouped = data.GroupBy(d => d).OrderBy(g => g.Key).ToList().Transpose();
String.Join(",", grouped.SelectMany(f => f));

结果是

411000A,411000B,411000C,411000D,411000A,411000B,411000C,411000D

给定以下名为的扩展方法Transpose

public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> @this) 
{
    var enumerators = @this.Select(t => t.GetEnumerator())
                           .Where(e => e.MoveNext()).ToList();

    while (enumerators.Any()) {
        yield return enumerators.Select(e => e.Current);
        enumerators = enumerators.Where(e => e.MoveNext()).ToList();
    }
}

另一种方法,实施Karel Frajtak的建议:

var result = data.GroupBy(d => d)
                 .SelectMany(g => g.Select((item, indexer) => new { item, indexer}))
                 .OrderBy(a => a.indexer)
                 .ThenBy(a => a.item)
                 .Select(a => a.item);
于 2013-10-04T13:47:44.953 回答
0

虽然不是最优的,但 IEnumerable> 上的递归扩展方法可能使用起来很有趣,并且在分组之外的一些更一般的情况下有用:

public static class GroupExtender
{
    public static IEnumerable<T> Mix<T>(this IEnumerable<IEnumerable<T>> groups)
    {
        // enumerate once
        var enumerable = groups as IList<IEnumerable<T>> ?? groups.ToList(); 
        //stop case
        if (!(enumerable.Any(g=>g.Any())))
            return new List<T>();
        // get first elements, iterate over the IEnumerable trimmed of these
        return enumerable
                .SelectMany(g => g.Take(1))
                .Concat(enumerable.Select(g => g.Skip(1)).Mix());
    }
}

获得“订购”的物品将是:

var _DrawingListInOrder = 
      _DrawingList.GroupBy(x => x.DrawingName).OrderBy(g => g.Key).Mix();
于 2013-10-04T15:04:46.930 回答