c#通过附加可变数量的空格使字符串列表的元素唯一
c# make elements of list of string unique, by appending variable number of spaces
我有一个小算法问题,我被困在一个(快速)实现中。
实际上我的还没有完成,但已经在减慢 DataGridView 的负载。
初始问题:
WinForms 的 DataGridView 有一个 2005 年的错误(显然直到 VS2015 仍未解决),导致错误地绑定具有相同名称的列不区分大小写。如果您有 2 列 "Cat" 和 "cat",则更精确,它们将绑定到数据库中的相同(第一个找到的)对象。
无论如何,我正在使用 ITypedList 和 GetItemProperties() 来通知 DGV 我想要 link 的字段。这个想法(在 Whosebug 的某处看到)是在 "duplicate case in-sensitive" 列的名称之后添加 spaces,如下所示:
"cat" --> leave as is
"Cat" --> needs to be come "Cat_" _ means space
"cAt" --> needs to become "cAt__" __ means two spaces and so on
算法问题:
使用循环在列表中添加字符串。在添加之前,检查字符串是否存在(trim 且不区分大小写),如果存在,则在名称末尾附加一个 space。保持名称不变。换句话说,通过将 n spaces 附加到名称来使字符串唯一。
希望我描述得很好,任何想法都会受到赞赏。
我已经对我的变体进行了一些测试,速度受到影响,也许 DGV 触发 GetItemProperties() 回调 5 次或更多次。
这是我的代码:
public partial class Form1 : Form
{
List<string> list = new List<string>
{
"cat", // the cat
"Cat", // first duplicate needs to become Cat_ (one space)
"kitty",
"kittY",
"dog",
"cAt", // third duplicate needs to become cAt__ (two spaces)
"Dog",
"monkey",
"monKey",
"Monkey",
};
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
AnimalHeaders phList = new AnimalHeaders();
for (int i = 0; i < list.Count(); i++)
{
string field = list.ElementAt(i);
var caseInsenList = phList.Where(z => z.Name.Trim().Equals(field, StringComparison.OrdinalIgnoreCase));
int count = caseInsenList.Count();
if (count == 0) // no results
{
phList.Add(new AnimalHeader { Name = field });
}
else // exists but can be many
{
for (j = 0; j < count; j++)
{
string found = caseInsenList.ElementAt(j).Name.Trim(); // no spaces
if (field == found)
continue; // exact match, case sensitive, we already have this, skip
else
{
}
}
}
}
}
}
public class AnimalHeader
{
public string Name { get; set; }
public Type Type { get; set; }
public int Order { get; set; }
}
public class AnimalHeaders : List<AnimalHeader>
{
}
尝试一个简单的 Linq:我们分组 相同的项目,然后添加 index
个空格(下划线)到每个 index
组中的第一个项目。最后,我们 flatten(合并)所有组。
List<string> list = new List<string>() {
"cat", // the cat
"Cat", // first duplicate needs to become Cat_ (one space)
"kitty",
"kittY",
"dog",
"cAt", // third duplicate needs to become cAt__ (two spaces)
"Dog",
"monkey",
"monKey",
"Monkey",
};
List<string> result = list
.GroupBy(item => item, StringComparer.OrdinalIgnoreCase)
.SelectMany(chunk => chunk
.Select((item, index) => string.Format("{0}{1}", item, new string('_', index))))
.ToList();
演示:
Console.WriteLine(string.Join(Environment.NewLine, result));
结果:
cat
Cat_
cAt__
kitty
kittY_
dog
Dog_
monkey
monKey_
Monkey__
编辑: 如果我们想保留 初始订单,我们必须存储它(index
初始列表中的项目),最后 order by it:
List<string> result = list
.Select((value, index) => new {
value,
index
})
.GroupBy(item => item.value, StringComparer.OrdinalIgnoreCase)
.SelectMany(chunk => chunk
.Select((item, index) => new {
value = string.Format("{0}{1}", item.value, new string('_', index)),
index = item.index
}))
.OrderBy(item => item.index)
.Select(item => item.value)
.ToList();
结果:
cat
Cat_
kitty
kittY_
dog
cAt__
Dog_
monkey
monKey_
Monkey__
我有一个小算法问题,我被困在一个(快速)实现中。 实际上我的还没有完成,但已经在减慢 DataGridView 的负载。
初始问题: WinForms 的 DataGridView 有一个 2005 年的错误(显然直到 VS2015 仍未解决),导致错误地绑定具有相同名称的列不区分大小写。如果您有 2 列 "Cat" 和 "cat",则更精确,它们将绑定到数据库中的相同(第一个找到的)对象。
无论如何,我正在使用 ITypedList 和 GetItemProperties() 来通知 DGV 我想要 link 的字段。这个想法(在 Whosebug 的某处看到)是在 "duplicate case in-sensitive" 列的名称之后添加 spaces,如下所示:
"cat" --> leave as is
"Cat" --> needs to be come "Cat_" _ means space
"cAt" --> needs to become "cAt__" __ means two spaces and so on
算法问题: 使用循环在列表中添加字符串。在添加之前,检查字符串是否存在(trim 且不区分大小写),如果存在,则在名称末尾附加一个 space。保持名称不变。换句话说,通过将 n spaces 附加到名称来使字符串唯一。
希望我描述得很好,任何想法都会受到赞赏。
我已经对我的变体进行了一些测试,速度受到影响,也许 DGV 触发 GetItemProperties() 回调 5 次或更多次。
这是我的代码:
public partial class Form1 : Form
{
List<string> list = new List<string>
{
"cat", // the cat
"Cat", // first duplicate needs to become Cat_ (one space)
"kitty",
"kittY",
"dog",
"cAt", // third duplicate needs to become cAt__ (two spaces)
"Dog",
"monkey",
"monKey",
"Monkey",
};
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
AnimalHeaders phList = new AnimalHeaders();
for (int i = 0; i < list.Count(); i++)
{
string field = list.ElementAt(i);
var caseInsenList = phList.Where(z => z.Name.Trim().Equals(field, StringComparison.OrdinalIgnoreCase));
int count = caseInsenList.Count();
if (count == 0) // no results
{
phList.Add(new AnimalHeader { Name = field });
}
else // exists but can be many
{
for (j = 0; j < count; j++)
{
string found = caseInsenList.ElementAt(j).Name.Trim(); // no spaces
if (field == found)
continue; // exact match, case sensitive, we already have this, skip
else
{
}
}
}
}
}
}
public class AnimalHeader
{
public string Name { get; set; }
public Type Type { get; set; }
public int Order { get; set; }
}
public class AnimalHeaders : List<AnimalHeader>
{
}
尝试一个简单的 Linq:我们分组 相同的项目,然后添加 index
个空格(下划线)到每个 index
组中的第一个项目。最后,我们 flatten(合并)所有组。
List<string> list = new List<string>() {
"cat", // the cat
"Cat", // first duplicate needs to become Cat_ (one space)
"kitty",
"kittY",
"dog",
"cAt", // third duplicate needs to become cAt__ (two spaces)
"Dog",
"monkey",
"monKey",
"Monkey",
};
List<string> result = list
.GroupBy(item => item, StringComparer.OrdinalIgnoreCase)
.SelectMany(chunk => chunk
.Select((item, index) => string.Format("{0}{1}", item, new string('_', index))))
.ToList();
演示:
Console.WriteLine(string.Join(Environment.NewLine, result));
结果:
cat
Cat_
cAt__
kitty
kittY_
dog
Dog_
monkey
monKey_
Monkey__
编辑: 如果我们想保留 初始订单,我们必须存储它(index
初始列表中的项目),最后 order by it:
List<string> result = list
.Select((value, index) => new {
value,
index
})
.GroupBy(item => item.value, StringComparer.OrdinalIgnoreCase)
.SelectMany(chunk => chunk
.Select((item, index) => new {
value = string.Format("{0}{1}", item.value, new string('_', index)),
index = item.index
}))
.OrderBy(item => item.index)
.Select(item => item.value)
.ToList();
结果:
cat
Cat_
kitty
kittY_
dog
cAt__
Dog_
monkey
monKey_
Monkey__