假设我有一个看起来像这样的文件:
R34 128590 -74.498 109.728 0 0805_7
R33 128590 -74.498 112.014 0 0805_7
R15 128588 -68.910 127.254 0 0805_7
R32 128587 -65.354 115.189 0 0805_7
R35 128587 -65.354 117.348 0 0805_7
R38 128590 -65.354 119.507 0 0805_7
我想要做的是将第二列添加到一个列表中并使用计数器计算该项目发生的次数,然后输出该数字,然后输出该数字的计数金额。< / p>
有没有办法使用List执行此操作?如果是这样,我怎么能这样做呢?
我试过搞乱事情,这就是我要去的地方......但它无法正常工作
int lineCount = 1;
int itemCounter = 0;
foreach (var item in aListBox.Items)
{
// Creates a string of the items in the ListBox.
var newItems = item.ToString();
// Replaces any multiple spaces (tabs) with a single space.
newItems = Regex.Replace(newItems, @"\s+", " ");
// Splits each line by spaces.
var eachItem = newItems.Split(' ');
###
### HERE is where I need help ###
###
List<string> partList = new List<string>();
partList.Add(eachItem[1]);
if (partList.Contains(eachItem[1]))
itemCounter++;
else
partList.Add(eachItem[1]);
sw.WriteLine(lineCount + ": "+ partList + ": " + itemCounter);
lineCount++;
}
对于上面的示例,SO ,它会输出:
1: 128590: 3 #lineCount, partList, itemCounter
2: 128588: 1
3: 128587: 2
有人可以帮我弄清楚如何正确地做到这一点吗?
答案 0 :(得分:4)
使用linq with count and group by(参见Count-Grouped部分)。
在foreach循环之外创建partList
并在循环内添加每个项目,以便它包含所有元素:
List<string> partList = new List<string>();
foreach (var item in aListBox.Items)
{
//regex stuff here...
partList.Add(eachItem[1]);
}
(在你的例子中 - {128590, 128590, 128588, 128587, 128587, 128590}
)
然后使用LINQ输出结果 -
var elementsWithCounts = from p in partList
group p by p into g
select new { Item = g.Key, Count = g.Count()};
答案 1 :(得分:2)
我会使用Linq查询或字典
类似
List<string> items = new List<string>{"128590", "128590", "128588", "128587", "128587", "128590"};
Dictionary<string,int> result = new Dictionary<string,int>();
foreach( int item in items )
{
if(result.ContainsKey(item) )
result[item]++;
else
result.Add(item,1);
}
foreach( var item in result )
Console.Out.WriteLine( item.Key + ":" + item.Value );
答案 2 :(得分:1)
一旦你按空格分割项目,我假设你有一个字符串数组:
[0] = "R34"
[1] = "128590"
[2] = "-74.498"
[3] = "109.728"
[4] = "0"
[5] = "0805_7"
您只需使用分组依据操作即可执行此操作。
var items = aListBox.Items.Select(x => /* Split Code Here and Take Element 1 */).GroupBy(x => x);
foreach(var set in items)
{
Console.WriteLine(set.Key + " appeared " + set.Count() + " times.");
}
答案 3 :(得分:1)
基本上,你试图通过迭代一次来做到这一点,而这实际上不会起作用,你将不得不迭代两次,否则你每次循环在foreach时都会结束输出,并且即使你准确的每次都要输出一条新线。如果你需要真正使用List而不是键控字典或散列表(这可能是想法)(key = number,value = count),那么你需要先构建列表,然后汇总列表。您可以使用LINQ Group By(这有点简洁),也可以创建一个与您已有的功能类似的功能。如果您正在尝试学习概念,请查看下面的代码,它可能更加简洁,但这应该相当容易阅读。
List<string> partList = new List<string>();
List<string> displayedNumbers = new List<int>();
// Build the original list first.
foreach (var item in aListBox.Items)
{
// Creates a string of the items in the ListBox.
var newItems = item.ToString();
// Replaces any multiple spaces (tabs) with a single space.
newItems = Regex.Replace(newItems, @"\s+", " ");
// Splits each line by spaces.
var eachItem = newItems.Split(' ');
partList.Add(eachItem[1]);
}
// Now run through that list and count how many times the same number occurs.
// You will need two loops for this since your list is a single dimension collection.
foreach(var number in partList)
{
var innerList = partList;
// set this to zero because we are going to find at least 1 duplicate.
var count = 0;
foreach(var additionalNumber in innerList)
{
if(additionalNumber == number)
{
// If we find anymore increase the count each time.
count += 1;
}
}
// Now we have the full count of duplicates of the outer number in the list.
// If it has NOT been displayed, display it.
if(!displayedNumbers.Contains(number))
{
sw.WriteLine(partList + ": " + count);
displayedNumbers.Add(number);
}
}
答案 4 :(得分:0)
使用哈希表而不是列表。您可以将密钥保存为128590,...以及值已发生的次数。 在插入新值之前,请使用包含操作检查哈希表中是否已存在该值,并且是否增加该值。
答案 5 :(得分:0)
我认为最大的问题是从文本字段的原始行到单个值。我的猜测是这是一个带有已知常数列的制表符分隔文件,在这种情况下,您可以使用String.Split()来分隔子字符串。将字符串分开后,可以使用一点LINQ轻松地计算正确列的实例。给出文件行的列表或集合:
var histogram = myListOfLines
//Split each string along spaces or tabs, and discard any zero-length strings
//caused by multiple adjacent delimiters.
.Select(s=>s.Split(new[]{'\t',' '}, StringSplitOptions.RemoveEmptyEntries))
//Optional; turn the array of strings produced by Split() into an anonymous type
.Select(a=>new{Col1=a[0], Col2=a[1], Col3=a[2], Col4=a[3], Col5=a[4]})
//Group based on the values of the second column.
.GroupBy(x=>x.Col2)
//Then, out of the grouped collection, get the count for each unique value of Col2.
.Select(gx=>new{gx.Key, gx.Count()});