如何将排序的字典输出到CSV?

时间:2014-10-17 11:23:01

标签: c# algorithm dictionary c#-3.0

我有一个排序字典,如下图所示:

  var enteries = new SortedDictionary<IgaAdKey, IgaEntry>();

enter image description here

我想在第一行,CSV格式中打印项目0,然后是项目2,然后是项目4,然后转到第1,3,5项并在CSV行上打印它们。 但有些情况下,只有3个唯一资源,或仅有3个唯一ResourceId值,而只有一个ResourceId。 在这些情况下,我想通过写5个逗号(“,,,,,”)打印一个空行。

以下是我的做法,但当然我正在跳过新的行

   foreach (var pair in enteries.OrderBy(pair => pair.Key.ResourceId))
    {
        if (!currResources.Contains(pair.Key.ResourceId))
        {
            currResources.Add(pair.Key.ResourceId);

            IgaEntry entry = enteries[pair.Key];

            streamWriter.Write(pair.Key.LocationId + ",");
            streamWriter.Write(pair.Key.EditionId + ",");
            streamWriter.Write(entry.mClickCount + ",");
            streamWriter.Write(entry.mViewCount + ",");
            streamWriter.Write(",");
        }
        else
        {
            IgaEntry entry = enteries[pair.Key];

            streamWriter.Write("\n");
            streamWriter.Write(date.ToString("yyyyMMdd") + ",");

            int search = resourcesList.IndexOf(pair.Key.ResourceId);
            if (search > 0)
            {
                for (int i = 0; i < search * 5; i++)
                {
                    streamWriter.Write(",");
                }
            }
            streamWriter.Write(pair.Key.LocationId + ",");
            streamWriter.Write(pair.Key.EditionId + ",");
            streamWriter.Write(entry.mClickCount + ",");
            streamWriter.Write(entry.mViewCount + ",");
            streamWriter.Write(",");
        }
    }

}

该代码的结果是:

enter image description here

应该是这样的:

enter image description here

2 个答案:

答案 0 :(得分:1)

数据只需要一个“分组依据”来根据ResourceId进行组织。

例如,使用GroupBy()按ResourceId对数据进行排序,然后创建一个投影,其中包含应在同一行上打印的其他字段:

static void Main(string[] args)
{
    //TODO: Run your method to build entries.
    var entries = TestFill(); 

    var tree = entries.GroupBy(
        pair => pair.Key.ResourceId, 
        pair => new {EditionId = pair.Key.EditionId, LocationId = pair.Key.LocationId, ClickCount = pair.Value.ClickCount, ViewCount = pair.Value.ViewCount},
        (key, data) => new {ResourceId = key, Statistics = data.ToList()});

    var count = 0;
    foreach (var node in tree)
    {
        Console.Write("[" + (count++) + "]\t" + node.ResourceId);
        foreach (var item in node.Statistics)
        {
            Console.Write(String.Format(",{0},{1},{2},{3}", item.LocationId, item.EditionId, item.ClickCount, item.ViewCount));
        }
        Console.WriteLine();

    }

    Console.WriteLine("Press enter to continue...");
    Console.ReadLine();
}

答案 1 :(得分:1)

任务比看起来更复杂...你做得不对,因为StreamWriter在最后添加文本,如果你打印了第一个ResourceId的2个条目(写了2行) ),您无法返回第一行打印第二个ResourceId的条目。

我编写并调试了一些代码,这里是保证可编译和可运行的;)

class CSVOrderById
{
    class IgaAdKey: IComparable
    {
        public int ResourceId { get; set; }
        public int EditionId { get; set; }
        public int LocationId { get; set; }

        //required if added to Dictionary, not the correct implementation though
        public int CompareTo(object obj) 
        {
            IgaAdKey key = obj as IgaAdKey;

            if (key == null)
                return -1;
            else
                return (ResourceId + EditionId + LocationId).CompareTo(key.ResourceId + key.EditionId + key.LocationId);                
        }
    }

    class IgaEntry
    {
        public int mClickCount { get; set; }
        public int mViewCount { get; set; }
    }

    public static void Test()
    {
        var enteries = new SortedDictionary<IgaAdKey, IgaEntry>();

        enteries.Add(new IgaAdKey(){ ResourceId = 123, EditionId = 12313, LocationId = 2}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});
        enteries.Add(new IgaAdKey(){ ResourceId = 123, EditionId = 12332, LocationId = 2}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});
        enteries.Add(new IgaAdKey(){ ResourceId = 234, EditionId = 23413, LocationId = 1}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});
        //enteries.Add(new IgaAdKey(){ ResourceId = 234, EditionId = 23455, LocationId = 1}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});
        enteries.Add(new IgaAdKey(){ ResourceId = 789, EditionId = 78922, LocationId = 2}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});
        //enteries.Add(new IgaAdKey(){ ResourceId = 789, EditionId = 78999, LocationId = 2}, new IgaEntry(){ mClickCount = 2, mViewCount = 10});

        var list = enteries.ToList(); //inorder to call FindAll()
        var dic = new Dictionary<int, List<KeyValuePair<IgaAdKey, IgaEntry>>>();
        var streamWriter = new StreamWriter("a.csv");

        //first find all ResourceId's, 
        HashSet<int> currResourcesId = new HashSet<int>();
        foreach (var pair in list)
        {
            currResourcesId.Add(pair.Key.ResourceId); //result: 3 unique ResourceId's
        }
        int maxCount = 0; 
        foreach (int resourceId in currResourcesId)
        {
            List<KeyValuePair<IgaAdKey, IgaEntry>> sortedByResourcesId = list.FindAll(pair => pair.Key.ResourceId == resourceId);
            dic.Add(resourceId, sortedByResourcesId);
            if (sortedByResourcesId.Count > maxCount)
                maxCount = sortedByResourcesId.Count; //result: maxCount = 2 
        }

        //so we write 2 rows
        for (int run = 0; run < maxCount; run++) 
        {
            streamWriter.Write(System.DateTime.Now.ToString("yyyyMMdd") + ",");
            foreach (int resourceId in currResourcesId)
            {
                if (dic[resourceId].Count > run)
                {
                    streamWriter.Write(dic[resourceId][run].Key.LocationId + ",");
                    streamWriter.Write(dic[resourceId][run].Key.EditionId + ",");
                    streamWriter.Write(dic[resourceId][run].Value.mClickCount + ",");
                    streamWriter.Write(dic[resourceId][run].Value.mViewCount + ",");
                    streamWriter.Write(",");
                }
                else
                {
                    streamWriter.Write(",,,,,");
                }
            }

            if (run < maxCount)
                streamWriter.WriteLine();
        }

        streamWriter.Close();        
    }
}