我有一个List,每个Object包含一个字符串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做的事情吗? 如果没有,有人可以提供一些指示来完成这个吗?
答案 0 :(得分: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()));
这会计算字符串中的所有字符。
答案 1 :(得分:2)
var input = "112";
var result = input
.GroupBy(c => c).Select(g => new {Key = g.Key, Count = g.Count()});
在此之后,您可以对值执行任何操作,并将它们分配给您想要的任何变量。
答案 2 :(得分: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 );
}