0

我有一个包含字符串 xvalue 的每个对象的列表:

Object.xvalue = "112"  
Object.xvalue = "332"  
Object.xvalue = "213" 

我想创建一个包含每列计数的新列表:

对象#1:(1,3,2)

 int var1 = 1  
 int var2 = 1  
 int var3 = 1  

对象#2:(1,3,1)

 int var1 = 2  
 int var2 = 0  
 int var3 = 1

对象 #3:(2,2,3)

  int var1 = 0  
  int var2 = 2  
  int var3 = 1 

这是我可以使用 LINQ 做的事情吗?
如果没有,有人可以提供一些指示来实现这一点吗?

4

3 回答 3

5

我假设您想要以下内容:

var counts = list.Select(s => new
                 {
                     var1 = s.Count(c => c == '1'),
                     var2 = s.Count(c => c == '2'),
                     var3 = s.Count(c => c == '3')
                 });

对于可扩展以检测所有可能值的解决方案,您可能需要这样的东西:

var counts = list.Select(s => s.GroupBy(c => c)
                               .ToDictionary(g => g.Key, g => g.Count()));

这将计算字符串中的所有字符。

于 2013-07-02T15:26:05.727 回答
2
var input = "112";

var result = input
             .GroupBy(c => c).Select(g => new {Key = g.Key, Count = g.Count()});

在此之后,您可以对这些值执行任何操作并将它们分配给您想要的任何变量。

于 2013-07-02T15:30:05.267 回答
0

好的,所以我一开始没有正确理解这个问题,所以我的第一个答案有点偏离,这是我的第二次尝试,我决定不在 linq 中做所有事情,因为这会很快变得非常混乱,这是一个允许的版本任何类型的字符,并给出所有列的计数。

    private class Example 
    {
        public string xvalue { get; set; }
    }

    //this will give you matches per column for any amount of chars
    public static Dictionary<char, int[]> GetCount(IEnumerable<Example> matchAgainst,params char[] matches)
    {

        //maybe there is an easier way to do this in linq I am not sure
        List<string> flattenedColumns = new List<string>();
        foreach ( var target in matchAgainst ) 
        {
            for ( int i = 0 ; i < target.xvalue.Length ; i++ )
            {
                if ( flattenedColumns.Count <= i )
                {
                    flattenedColumns.Add ( string.Empty );
                }
                flattenedColumns [ i ] += target.xvalue [ i ];
            }
        }

        //now compose based on the chars
        return ( from c in matches
                 select new
                     {
                         CharTarget = c ,
                         Counts = ( from col in flattenedColumns
                                    select col.Count ( ( ch ) => ch == c ) ).ToArray ( )
                     } ).ToDictionary ( rslt => rslt.CharTarget , rslt => rslt.Counts );
    }

    public static void Do ( ) 
    {
        string curr = "";
        List<Example> exampleList = new List<Example> ( );
        for(int i=0;i<10;i++)
            for(int j=0;j<10;j++)
                for ( int k = 0 ; k < 10 ; k++ ) 
                {
                    curr= i+""+j+""+k;
                    exampleList.Add ( new Example { xvalue = curr } );
                }

        var matches = GetCount ( exampleList , '1' , '2' , '3' );
        var var1Col1 = matches [ '1' ] [ 0 ];
        var var2Col1 = matches [ '2' ] [ 0 ];
        //...
    }

注意: 我不确定这是否是展平列的最佳方法,但它似乎是最直接的。

这是一个更通用的版本,我假设列只是对象数组,为了展平列,我只使用聚合和一个私有定义的类,该类表示一个对象是否已转换为

private class Row
{
    public object[] Columns {get;set;}
}

public static Dictionary<object, int[]> GetCountByIndex(IEnumerable<Row> matchAgainst, params object[] matches)
{
    bool firstTime = true;
    return
    ( from key in matches
        let flatCols = ( from Row row in matchAgainst select row.Columns ).Aggregate ( ( a , b ) =>
        {
            var retlen = a.Length;

            if ( b.Length > a.Length )
                retlen = b.Length;

            object [ ] retv = new object [ retlen ];
            //use bool flag to determine first time objects are being aggregated
            if (!firstTime)
            {
                //do every other join
                for ( int i = 0 ; i < retlen ; i++ )
                {
                    List<object> curr = null;
                    if ( i >= a.Length )
                    {
                        curr = new List<object> ( );
                    }
                    else
                    {
                        curr = a [ i ] as List<object>;
                    }
                    if ( i < b.Length )
                    {
                        curr.Add ( b [ i ] );
                    }
                    retv [ i ] = curr;
                }

            }
            else
            {
                //intialization
                for ( int i = 0 ; i < retlen ; i++ )
                {
                    List<object> curr = new List<object>( );
                    if ( i < a.Length )
                    {
                        curr.Add ( a [ i ] );
                    }
                    if ( i < b.Length )
                    {
                        curr.Add ( b [ i ] );
                    }
                    retv [ i ] = curr;
                }
                firstTime = false;

            }
            return retv;
        } )
        select new
        {
            Key = key ,
            Value = ( from object obj in flatCols
                    select ( ( List<object> ) obj ).Count ( c => key.Equals ( c ) ) ).ToArray ( )

        } ).ToDictionary ( keySel => keySel.Key , valSel => valSel.Value );
}
于 2013-07-02T16:03:24.227 回答