在列表中添加和计数项目
本文关键字:项目 添加 列表 | 更新日期: 2023-09-27 18:05:17
假设我有一个像这样的文件:
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
我想要做的是将第二列添加到列表中,并让计数器计算该项目出现的次数,然后输出该数字和该数字的计数量。
是否有一种方法来做到这一点使用列表?如果是这样,我该怎么做呢?
我试过乱弄东西,这就是我要去的地方。但是它不能正常工作
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
谁能帮我弄清楚如何正确地做这件事?
使用linq与count和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()};
我会使用Linq查询或Dictionary
比如
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 );
一旦你有了按空格分割的项目,我假设你有一个字符串数组看起来像这样:
[0] = "R34"
[1] = "128590"
[2] = "-74.498"
[3] = "109.728"
[4] = "0"
[5] = "0805_7"
您可以简单地通过Group By操作来执行此操作。
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.");
}
基本上,你试图通过迭代一次来做到这一点,这并不会真正起作用,你将不得不迭代两次,否则你将在每次循环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);
}
}
使用哈希表而不是列表。您可以将密钥保存为128590,…这个值是它出现的次数。在插入新值之前,请使用Contains操作检查该值是否已经存在于哈希表中,以及该值是否增加。
我认为最大的问题是从文本字段的原始行到单个值。我的猜测是,这是一个以制表符分隔的文件,具有已知的常量列数,在这种情况下,可以使用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()});