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 的连接。等等

不要太在意字符串的细节;将“1”视为 object 的实例,将Word“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 回答