1

過度に単純化された不自然な質問

一連の連続した要素を含むことができる列挙可能なインスタンスと、それらと相互に分散された他の要素があります。簡単な例

var items = new[]
            {"1","1","1","1","1","varX","1","1","1","1","varY","1","1"};

ご覧のとおり、文字列1が繰り返され、時々別のものがあります (非常に認識可能)。列挙可能なものを形成する方法で集約したいとしましょう

var aggregated = new[]
          { "11111", "varX", "1111", "varY","11"};

これは明らかに、「連結されたすべての 1」の後に「var」が続き、その後に次の連結された 1 のセットが続きます。等

文字列の詳細にこだわりすぎないでください。Word「1」は object のインスタンス、「var」は object のインスタンスと考えてくださいVariable。今、私はWord(文を作るために)一緒に連結し、Variable別の方法で扱いたい

LINQ を使用して、または昔ながらの foreach を使用して、その集計を作成するにはどうすればよいでしょうか。

少し単純化された、同じ質問

「トークン」の列挙可能なリストがあります。トークンには 2 種類しかなく、どちらも基本トークンから継承されます。

public abstract class Token{}
public class WordToken : Token {}
public class VariableToken : Token {}

文字列:

こんにちは {varX} お元気ですか {varY} さようなら

私のコードによって次の列挙可能にトークン化されます

  var tokens = new[]
    { 
       WordToken, 
       WordToken, 
       VariableToken,  
       WordToken,  
       WordToken,  
       WordToken,  
       VariableToken,  
       WordToken
    };

私はそれを

var newList = new [] 
    {
       FragmentToken, 
       VariableToken,  
       FragmentToken,  
       VariableToken,  
       FragmentToken
     };

FragmentToken連結されたすべての単語はどこにありますか

明らかな最初のステップは、元のリストを集約して作成することです

var step = new[]
    { 
          new[]{WordToken, WordToken}, 
          new[]{VariableToken},
          new[]{ WordToken, WordToken, WordToken}, 
          new[]{VariableToken}, 
          new[]{WordToken}
    };

その後、次のステップを簡単に実行できましたが、この最初のステップに到達する方法がわかりません。

4

2 に答える 2

3

これはあなたが望む解決策に近いですか?

public abstract class Token : IComparable
{
    public int CompareTo(object obj)
    {
        if (obj == null)
        {
            return -1;
        }
        return GetType().FullName.CompareTo(obj.GetType().FullName);
    }
}
public class WordToken : Token { }
public class VariableToken : Token { }

public static class ListExtensions
{
    public static IEnumerable<IEnumerable<TEntity>> JoinRepeatedValues<TEntity>(this IEnumerable<TEntity> collection)
        where TEntity : IComparable
    {
        var joinedRepeatedValuesCollection = new List<List<TEntity>>();
        var lastValue = default(TEntity);
        foreach (var item in collection)
        {
            if (item.CompareTo(lastValue) != 0)
            {
                joinedRepeatedValuesCollection.Add(new List<TEntity> { item });
            }
            else
            {
                var lastAddedValue = joinedRepeatedValuesCollection.Last();
                lastAddedValue.Add(item);
            }
            lastValue = item;
        }
        return joinedRepeatedValuesCollection;
    }

}
class Program
{
    static void Main(string[] args)
    {
        var tokens = new Token[]
                            {
                                new WordToken(),
                                new WordToken(),
                                new VariableToken(),
                                new WordToken(),
                                new WordToken(),
                                new WordToken(),
                                new VariableToken(),
                                new WordToken()
                            };

        var joinedValues = tokens.JoinRepeatedValues();
        var items = new[] { "1", "1", "1", "1", "1", "varX", "1", "1", "1", "1", "varY", "1", "1" }.JoinRepeatedValues();
    }
}
于 2013-04-23T21:50:38.120 に答える
2

さて、これは問題の私の理解に基づいた試みです

var initialList;//whatever this contains...

List<List<Object>> retList = new List<List<Object>>();

Type storedType = null;

foreach(Object thing in initialList)
{//we treat this like a simple array of objects, because we DONT know what's in it.
    if(storedType != null)
    {
        if(storedType.Equals(thing.GetType())
            instanceList.Add(thing);
        else
        {//add instanceList to the master return, then re-set stored type and the 
         //list and add the current thing to the new list
            retList.Add(instanceList);
            storedType = thing.GetType();
            instanceList = new List<Object>();
            instanceList.Add(thing);
        }
    }
    else
    {//should be First run only
        storedType = thing.GetType();
        instanceList.Add(thing);
    }
}
return retList;

追記:

すべてのオブジェクトが同じであると想定されている場合は、Type型をチェックする代わりに、値をチェックして保存しますが、基本的なアルゴリズムは同じままです。また、 の代わりにコンテンツの正確なタイプを使用できますObject。これは、とにかく値をチェックする場合に必要です..

===========================================

現在のアイテムの順序を維持しながら、linq でこれを行う方法がわかりません。それが重要でない場合は、Linq のOfType<>方法を使用して、タイプに基づいてリストをフィルター処理します。残念ながら、そのために型指定で変数を使用することはできないため、initialList に含まれる可能性のあるすべての型の厳密なリストを事前に知っておく必要があります。

于 2013-04-23T21:17:32.437 に答える