1

次のようなテキストファイルにショッピングリストがあります。

BuyerId    Item;
1;         Item1;
1;         Item2;
1;         ItemN;
2;         Item1;
2;         ItemN;
3;         ItemN;

このリストを次のような形式に変換する必要があります。

Item1; Item2; Item3; ...; ItemN    <--- For buyer 1
Item1; ...; ItemN                  <--- For buyer 2
Item1; ...; ItemN                  <--- For buyer 3

まず、CSVファイルを次のように解析します。

IList<string[]> parsedcsv = (from line in lines.Skip(1) 
                             let parsedLine = line.TrimEnd(';').Split(';')
                             select parsedLine).ToList();

次に、アイテムをLINQでグループ化し、最終的な形式に集約します。

IEnumerable<string> buyers = from entry in parsedcsv
                             group entry by entry[0] into cart
                             select cart.SelectMany(c => c.Skip(1))
                                  .Aggregate((item1, item2) => 
                                      item1 + ";" + item2).Trim();

ただし、たまたま、BuyerIdは一意ではありませんが、何度も繰り返されます(たとえば、次のように繰り返すことができます:1,2,3,4,5,1,2,3,4,5,1 、2,3またはこのような1,2,3,1,2,3,1,2)。

大したことではありません。一度に1人の購入者のみと取引することを確認するループにアイテムをグループ化することで、これを非常に簡単に修正できます。

int lastBatchId = 0;
string currentId = parsedcsv[0][0];
for (int i = 0; i < parsedcsv.Count; i++)
{
    bool last = parsedcsv.Count - 1 == i;
    if (parsedcsv[i][0] != currentId || last)
    {
         IEnumerable<string> buyers = from entry in parsedcsv.Skip(lastBatchId)
              .Take(i - lastBatchId + (last ? 1 : 0))
         ...
         lastBatchId = i;
         currentId = parsedcsv[i][0];
         ...

...ただし、これは最も洗練されたソリューションではありません。これはLINQでのみ実行できるとほぼ確信しています。

誰かがここで私を助けてくれますか?

ありがとう!

4

2 に答える 2

1

GroupAdjacentを見てください。

于 2012-09-11T11:28:52.710 に答える
0

これが最善の解決策かどうかはわかりませんが、純粋なLinqの回答が必要だと言ったので、ここにあります:

var result = from r in (

    from l in lines.Skip(1)
    let data = l.Split(new string[]{";"," "}, 
                       StringSplitOptions.RemoveEmptyEntries)
    select new { Id = data.First(), Item = data.Skip(1).First() })
    .Aggregate(new 
                { 
                    Rows = Enumerable.Repeat(new 
                                            { 
                                                Id = string.Empty, 
                                                Items = new List<string>() 
                                            }, 1).ToList(), 
                    LastID = new List<string>() { "" } 
                }, 
                (acc, x) => 
                { 
                    if (acc.Rows[0].Id == string.Empty)
                        acc.Rows.Clear();
                    if (acc.LastID[0] != x.Id)
                        acc.Rows.Add(new 
                                    {
                                        Id = x.Id, 
                                        Items = new List<string>() 
                                    });
                    acc.Rows.Last().Items.Add(x.Item);
                    acc.LastID[0] = x.Id;
                    return acc; 
                }       
    ).Rows
select new 
{ 
    r.Id, 
    Items = string.Join(";", from x in r.Items 
                             select x) 
};

私はそれをかなり速く書いたので、改善することができます.2、3のトリックに頼っているので特に好きではありませんが、純粋なLinqであり、出発点になる可能性があります.

于 2012-09-11T14:53:56.137 に答える