计算 ListView 列中的所有重复项。 C#
Count all duplicates in ListView column. C#
我正在为市场创建一个软件,并想创建一个列表视图来计算列中的所有重复值。
此计数将显示买家经常购买的商品数量。
这才是ListView应该有的概念。
从ListView1的列开始统计,把重复的放到ListView2里面统计,显示数据。
我需要知道:
- 如何计算“已购买商品”列中的所有重复值。
- 并在另一个 ListView 中显示计数结果,并显示其本身的值。
注意:在这种情况下,“名称”中的值是一个项目,“已购买的项目”是一个子项目。这些数据来自简单地在文本框中键入并单击按钮。
可以使用 System.Linq.GroupBy
逻辑和 DataGridView
(Winforms 示例)视图来实现您想要的结果:
写的代码量小!只需对两个列表使用数据绑定 Winforms, Xamarin, WPF:
首先制作两个类包含您希望显示的属性:
internal class UserPurchase
{
public string Name { get; internal set; } // Internal makes item ReadOnly in view
public string Purchase { get; internal set; }
}
和
internal class PurchasedItem
{
public string Description { get; internal set; }
public int Count { get; internal set; }
}
然后声明两个BindingList
(Winforms示例)或ObservableCollection
(其他)。
internal BindingList<UserPurchase> PurchasesByUser { get; } = new BindingList<UserPurchase>();
internal BindingList<PurchasedItem> PurchasedByItem { get; } = new BindingList<PurchasedItem>();
这显示了如何在 Winforms 中附加绑定(对于其他平台,请使用 xaml)。因此 DataGridView
现在将使用两个 类.
的属性自动生成列
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
if (!DesignMode)
{
// Bind the lists to the UI element to display them.
dataGridView1.DataSource = PurchasesByUser;
dataGridView2.DataSource = PurchasedByItem;
initList1();
}
}
这是填充 List1
PurchasesByUser 然后在 List1
上应用 System.Linq.GroupBy
来计算 List2
PurchasedByItem:
private void initList1()
{
XElement xsource = XElement.Parse(source);
XElement[] xusers = xsource.Elements("user").ToArray();
foreach (XElement xuser in xusers)
{
XElement[] xpurchases = xuser.Element("items").Elements("item").ToArray();
foreach (XElement xpurchase in xpurchases)
{
var xname = xuser.Element("name");
// Every time you add a record to the list, it appears in the View automatically.
PurchasesByUser.Add(new UserPurchase { Name = (string)xname, Purchase = (string)xpurchase });
}
}
// Make what is essentially a list *of* lists using System.Linq.GroupBy
var groups =
PurchasesByUser.GroupBy(purchase => purchase.Purchase);
foreach (var group in groups)
{
// Decoding the Group:
Debug.WriteLine(
$"The group '{group.Key}' holds {group.Count()} items");
Debug.WriteLine(
$"The customers are { string.Join(",", group.ToList().Select(item=>item.Name))}");
var byItem = new PurchasedItem { Description = group.Key, Count = group.Count() };
PurchasedByItem.Add(byItem);
}
}
最后 为您的数据库建模(带有子项),我使用 Xml 格式的字符串:
const string source =
@"<purchases>
<user>
<name>John Doe</name>
<items>
<item>Shoes</item>
<item>T-Shirts</item>
<item>Jeans</item>
</items>
</user>
<user>
<name>Rick Astley</name>
<items>
<item>Baseball bat</item>
<item>Sandwich</item>
<item>T-Shirts</item>
<item>Shoes</item>
</items>
</user>
<user>
<name>Jane Doe</name>
<items>
<item>Shoes</item>
<item>T-Shirts</item>
</items>
</user>
<user>
<name>Anonymous</name>
<items>
<item>Laptop</item>
</items>
</user>
<user>
<name>Joe Mm.</name>
<items>
<item>Milk</item>
<item>Shoes</item>
</items>
</user>
</purchases>";
这当然只是一种方法,但您的问题是演示结合 System.Linq
System.Xml.Linq
和数据绑定概念的好方法。如果您想试验一下,我已将我的代码发布在 GitHub 上。
那么,如果我知道你想要另一个包含重复项和计数的列表视图?
如果是这样,您可以创建一个 List<>,然后将该项目添加到列表中,我相信在这种情况下将是一个字符串,也许是这样的?这只是一个用于演示的控制台应用程序。
List<string> myList = new List<string>();
myList.Add("One");
myList.Add("Two");
myList.Add("Three");
myList.Add("One");
myList.Add("Two");
myList.Add("Four");
List<string> noDupes = myList.Distinct().ToList();
foreach(string dupe in noDupes)
{
Console.WriteLine(dupe);
}
Console.WriteLine(noDupes.Count());
给定下一个列表:
List<myClass> items = new List<myClass>()
{
new myClass() { Name = "John Doe", Item = "Shoes" },
new myClass() { Name = "John Doe", Item = "T-Shirt" },
new myClass() { Name = "John Doe", Item = "Jeans" },
new myClass() { Name = "Rick Astley", Item = "Baseball bat" },
new myClass() { Name = "Rick Astley", Item = "Sandwich" },
new myClass() { Name = "Rick Astley", Item = "T-Shirt" },
new myClass() { Name = "Rick Astley", Item = "Shoes" },
new myClass() { Name = "Jane Doe", Item = "Shoes" },
new myClass() { Name = "Jane Doe", Item = "T-Shirt" },
new myClass() { Name = "Joe Mm.", Item = "Shoes" },
new myClass() { Name = "Joe Mm.", Item = "Milk" },
};
可以这样分组统计:
var l = items.GroupBy(group => group.Item)
.Select(n => new { Item = n.Key, Count = n.Count() })
.ToList();
结果:
Item: Shoes Count: 4
Item: T-Shirt Count: 3
Item: Jeans Count: 1
Item: Baseball bat Count: 1
Item: Sandwich Count: 1
Item: Milk Count: 1
将输入 ListView
的项目按第二个 ColumnHeader
(索引 = 1)的值分组得到 IEnumerable<IGrouping<string, ListViewItem>>
,然后使用元素(类型 IGrouping<string, ListViewItem>
) Key
属性 和 Count
方法创建输出 ListView
.
的 ListViewItem
对象
这是一个衬垫:
listView2.Items.AddRange(listView1.Items
.Cast<ListViewItem>()
.GroupBy(x => x.SubItems[1].Text, StringComparer.OrdinalIgnoreCase)
.Select(x => new ListViewItem(new[] { x.Key, x.Count().ToString() }))
.ToArray());
我正在为市场创建一个软件,并想创建一个列表视图来计算列中的所有重复值。
此计数将显示买家经常购买的商品数量。
这才是ListView应该有的概念。 从ListView1的列开始统计,把重复的放到ListView2里面统计,显示数据。
我需要知道:
- 如何计算“已购买商品”列中的所有重复值。
- 并在另一个 ListView 中显示计数结果,并显示其本身的值。
注意:在这种情况下,“名称”中的值是一个项目,“已购买的项目”是一个子项目。这些数据来自简单地在文本框中键入并单击按钮。
可以使用 System.Linq.GroupBy
逻辑和 DataGridView
(Winforms 示例)视图来实现您想要的结果:
写的代码量小!只需对两个列表使用数据绑定 Winforms, Xamarin, WPF:
首先制作两个类包含您希望显示的属性:
internal class UserPurchase
{
public string Name { get; internal set; } // Internal makes item ReadOnly in view
public string Purchase { get; internal set; }
}
和
internal class PurchasedItem
{
public string Description { get; internal set; }
public int Count { get; internal set; }
}
然后声明两个BindingList
(Winforms示例)或ObservableCollection
(其他)。
internal BindingList<UserPurchase> PurchasesByUser { get; } = new BindingList<UserPurchase>();
internal BindingList<PurchasedItem> PurchasedByItem { get; } = new BindingList<PurchasedItem>();
这显示了如何在 Winforms 中附加绑定(对于其他平台,请使用 xaml)。因此 DataGridView
现在将使用两个 类.
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
if (!DesignMode)
{
// Bind the lists to the UI element to display them.
dataGridView1.DataSource = PurchasesByUser;
dataGridView2.DataSource = PurchasedByItem;
initList1();
}
}
这是填充 List1
PurchasesByUser 然后在 List1
上应用 System.Linq.GroupBy
来计算 List2
PurchasedByItem:
private void initList1()
{
XElement xsource = XElement.Parse(source);
XElement[] xusers = xsource.Elements("user").ToArray();
foreach (XElement xuser in xusers)
{
XElement[] xpurchases = xuser.Element("items").Elements("item").ToArray();
foreach (XElement xpurchase in xpurchases)
{
var xname = xuser.Element("name");
// Every time you add a record to the list, it appears in the View automatically.
PurchasesByUser.Add(new UserPurchase { Name = (string)xname, Purchase = (string)xpurchase });
}
}
// Make what is essentially a list *of* lists using System.Linq.GroupBy
var groups =
PurchasesByUser.GroupBy(purchase => purchase.Purchase);
foreach (var group in groups)
{
// Decoding the Group:
Debug.WriteLine(
$"The group '{group.Key}' holds {group.Count()} items");
Debug.WriteLine(
$"The customers are { string.Join(",", group.ToList().Select(item=>item.Name))}");
var byItem = new PurchasedItem { Description = group.Key, Count = group.Count() };
PurchasedByItem.Add(byItem);
}
}
最后 为您的数据库建模(带有子项),我使用 Xml 格式的字符串:
const string source =
@"<purchases>
<user>
<name>John Doe</name>
<items>
<item>Shoes</item>
<item>T-Shirts</item>
<item>Jeans</item>
</items>
</user>
<user>
<name>Rick Astley</name>
<items>
<item>Baseball bat</item>
<item>Sandwich</item>
<item>T-Shirts</item>
<item>Shoes</item>
</items>
</user>
<user>
<name>Jane Doe</name>
<items>
<item>Shoes</item>
<item>T-Shirts</item>
</items>
</user>
<user>
<name>Anonymous</name>
<items>
<item>Laptop</item>
</items>
</user>
<user>
<name>Joe Mm.</name>
<items>
<item>Milk</item>
<item>Shoes</item>
</items>
</user>
</purchases>";
这当然只是一种方法,但您的问题是演示结合 System.Linq
System.Xml.Linq
和数据绑定概念的好方法。如果您想试验一下,我已将我的代码发布在 GitHub 上。
那么,如果我知道你想要另一个包含重复项和计数的列表视图?
如果是这样,您可以创建一个 List<>,然后将该项目添加到列表中,我相信在这种情况下将是一个字符串,也许是这样的?这只是一个用于演示的控制台应用程序。
List<string> myList = new List<string>();
myList.Add("One");
myList.Add("Two");
myList.Add("Three");
myList.Add("One");
myList.Add("Two");
myList.Add("Four");
List<string> noDupes = myList.Distinct().ToList();
foreach(string dupe in noDupes)
{
Console.WriteLine(dupe);
}
Console.WriteLine(noDupes.Count());
给定下一个列表:
List<myClass> items = new List<myClass>()
{
new myClass() { Name = "John Doe", Item = "Shoes" },
new myClass() { Name = "John Doe", Item = "T-Shirt" },
new myClass() { Name = "John Doe", Item = "Jeans" },
new myClass() { Name = "Rick Astley", Item = "Baseball bat" },
new myClass() { Name = "Rick Astley", Item = "Sandwich" },
new myClass() { Name = "Rick Astley", Item = "T-Shirt" },
new myClass() { Name = "Rick Astley", Item = "Shoes" },
new myClass() { Name = "Jane Doe", Item = "Shoes" },
new myClass() { Name = "Jane Doe", Item = "T-Shirt" },
new myClass() { Name = "Joe Mm.", Item = "Shoes" },
new myClass() { Name = "Joe Mm.", Item = "Milk" },
};
可以这样分组统计:
var l = items.GroupBy(group => group.Item)
.Select(n => new { Item = n.Key, Count = n.Count() })
.ToList();
结果:
Item: Shoes Count: 4
Item: T-Shirt Count: 3
Item: Jeans Count: 1
Item: Baseball bat Count: 1
Item: Sandwich Count: 1
Item: Milk Count: 1
将输入 ListView
的项目按第二个 ColumnHeader
(索引 = 1)的值分组得到 IEnumerable<IGrouping<string, ListViewItem>>
,然后使用元素(类型 IGrouping<string, ListViewItem>
) Key
属性 和 Count
方法创建输出 ListView
.
ListViewItem
对象
这是一个衬垫:
listView2.Items.AddRange(listView1.Items
.Cast<ListViewItem>()
.GroupBy(x => x.SubItems[1].Text, StringComparer.OrdinalIgnoreCase)
.Select(x => new ListViewItem(new[] { x.Key, x.Count().ToString() }))
.ToArray());