C# 用于显示包含字符串字段的行的二进制搜索数组
我有一个按钮,它应该接受“姓氏”字符串输入,在目录数组中搜索与该姓氏相关的“记录”结构,并将该记录输出到listview。该目录由许多行3个字符串记录结构组成:姓氏、名字、extcode 经过几天对类似的SO问题和其他来源的搜索,我拼凑出了似乎最适合我的问题的方法,但出于某种原因,我的主要搜索方法并没有引用我的次要方法。你能告诉我你为什么这么认为吗?如果我能让参考资料发挥作用,你认为这是否有效?如果不行,还有其他的建议吗 仅供参考,我的if语句有点难以控制,因为我的项目要求姓氏不区分大小写,并接受部分字符串匹配C# 用于显示包含字符串字段的行的二进制搜索数组,c#,arrays,string,binary-search,C#,Arrays,String,Binary Search,我有一个按钮,它应该接受“姓氏”字符串输入,在目录数组中搜索与该姓氏相关的“记录”结构,并将该记录输出到listview。该目录由许多行3个字符串记录结构组成:姓氏、名字、extcode 经过几天对类似的SO问题和其他来源的搜索,我拼凑出了似乎最适合我的问题的方法,但出于某种原因,我的主要搜索方法并没有引用我的次要方法。你能告诉我你为什么这么认为吗?如果我能让参考资料发挥作用,你认为这是否有效?如果不行,还有其他的建议吗 仅供参考,我的if语句有点难以控制,因为我的项目要求姓氏不区分大小写,并接
private void SearchSurname()
{
Array.Sort(directory, (x, y) => String.Compare(x.surname, y.surname));
ClearForm();
int surnameIndex = Array.BinarySearch(directory, txtSurname.Text);
if (directory[surnameIndex].surname.ToUpper().Substring(0, txtSurname.Text.Length).Contains(txtSurname.Text.ToUpper()))
{
ListViewItem record = new ListViewItem();
// Send each field in current record to single listview item
record.Text = (Convert.ToString(txtSurname.Text));
record.SubItems.Add(Convert.ToString(txtForename.Text));
record.SubItems.Add(Convert.ToString(txtExtCode.Text));
// Display new record listview item in listview
lvDirectory.Items.Add(record);
}
}
public int BinarySearch(string[] directory, string searchTerm)
{
int first = 0;
int last = directory.Length - 1;
int position = -1;
bool found = false;
int compCount = 0;
searchTerm = txtSurname.Text;
while (found != true && first <= last)
{
int middle = (first + last) / 2;
if (string.Compare(directory[middle], searchTerm, true) == 0)
{
found = true;
position = middle;
compCount++;
}
else if (string.Compare(directory[middle], searchTerm, true) > 0)
{
last = middle;
compCount++;
}
else
{
first = middle;
compCount++;
}
}
return position;
}
private void searchname()
{
Sort(directory,(x,y)=>String.Compare(x.lasname,y.lasname));
ClearForm();
int-namesindex=Array.BinarySearch(目录,txtnusname.Text);
if(目录[姓氏索引]。姓氏.ToUpper().Substring(0,txtnamname.Text.Length)。包含(txtnamname.Text.ToUpper())
{
ListViewItem记录=新建ListViewItem();
//将当前记录中的每个字段发送到单个listview项
record.Text=(Convert.ToString(txtnamname.Text));
record.SubItems.Add(Convert.ToString(txtForename.Text));
record.SubItems.Add(Convert.ToString(txtExtCode.Text));
//在listview中显示新记录listview项
lvDirectory.Items.Add(记录);
}
}
公共int二进制搜索(字符串[]目录,字符串搜索项)
{
int first=0;
int last=directory.Length-1;
int位置=-1;
bool-found=false;
int compCount=0;
searchTerm=txtNames.Text;
while(找到!=true&&first 0)
{
最后=中间;
compCount++;
}
其他的
{
第一个=中间;
compCount++;
}
}
返回位置;
}
编辑:根据Olivier Jacot Descombes的回答更新代码:
private void SearchSurname()
{
// Sort directory alphabetically by surname
Array.Sort(directory, (x, y) => String.Compare(x.surname, y.surname));
ClearForm();
// In directory, find line index of search term
int surnameIndex = BinarySearch(directory, txtSurname.Text);
ListViewItem record = new ListViewItem();
// Send each field in current record to single listview item
record.Text = (Convert.ToString(directory[surnameIndex].surname));
record.SubItems.Add(Convert.ToString(directory[surnameIndex].forename));
record.SubItems.Add(Convert.ToString(directory[surnameIndex].extCode));
// Display new record listview item in listview
lvDirectory.Items.Add(record);
}
private int BinarySearch(record[] directory, string searchTerm)
{
int first = 0;
int last = directory.Length - 1;
int surnameIndex = -1;
bool indexFound = false;
// While index not found and there are still points in the array to check
while (indexFound != true && first < last)
{
int middle = (first + last) / 2;
// If surname field in middle record of directory array matches the search term
if (string.Compare(directory[middle].surname, searchTerm, true) == 0)
{
// Index found!
indexFound = true;
surnameIndex = middle;
MessageBox.Show("If 1");
}
// If surname field in middle record of directory array is higher, alphabetically, than the search term
else if(string.Compare(directory[middle].surname, searchTerm, true) > 0)
{
// The next search will be between the first and the current middle records of the array
last = middle;
MessageBox.Show("If 2");
}
// If surname field in middle record of directory array is lower, alphabetically, than the search term
else
{
// The next search will be between the current middle and the highest records of the array
first = middle;
MessageBox.Show("If 3");
}
}
return surnameIndex;
}
private void searchname()
{
//按姓氏按字母顺序对目录排序
Sort(directory,(x,y)=>String.Compare(x.lasname,y.lasname));
ClearForm();
//在目录中,查找搜索项的行索引
int-namesindex=BinarySearch(目录,txtnusname.Text);
ListViewItem记录=新建ListViewItem();
//将当前记录中的每个字段发送到单个listview项
record.Text=(Convert.ToString(目录[姓氏索引].姓氏));
record.SubItems.Add(Convert.ToString(目录[namesindex].forename));
record.SubItems.Add(Convert.ToString(目录[namesindex].extCode));
//在listview中显示新记录listview项
lvDirectory.Items.Add(记录);
}
私有int二进制搜索(记录[]目录,字符串搜索项)
{
int first=0;
int last=directory.Length-1;
int指数=-1;
bool indexFound=false;
//虽然未找到索引,但数组中仍有要检查的点
while(indexFound!=true&&first0)
{
//下一次搜索将在数组的第一个和当前中间记录之间进行
最后=中间;
MessageBox.Show(“如果2”);
}
//如果目录数组中间记录中的姓氏字段按字母顺序低于搜索词
其他的
{
//下一次搜索将在数组的当前中间记录和最高记录之间进行
第一个=中间;
MessageBox.Show(“如果3”);
}
}
回归指数;
}
您的searchname
方法调用Array.BinarySearch
,它是的静态方法。如果要调用自己的方法,则必须编写:
int surnameIndex = BinarySearch(directory, txtSurname.Text); // Without "Array."
您通过String的第三个参数使用不区分大小写的比较。比较true
你可以用
if (string.StartsWith(directory[middle], searchTerm,
StringComparison.CurrentCultureIgnoreCase))
仅搜索名称的开头。但如果几个名字匹配,就会出现问题。例如,您正在搜索“smit”
,数组中有“Smith”
和“Smithy”
。因此,您必须在找到匹配项之前和之后测试条目,并返回所有匹配项作为可能的结果。感谢您的澄清——我无法决定是否使用此选项。根据您的建议,我已删除了此项,但在对目录的引用中,我现在收到错误“无法从'PhoneDirectory.frmPhoneDirectory.record[]”转换为'string[]”。您能告诉我如何解决这个问题吗?您的数组的类型似乎是record[]
,而不是string[]
。因此,请更改您的方法:public int BinarySearch(record[]目录,string searchTerm)
当我将方法更改为,public int BinarySearch(record[]目录,string searchTerm)
时,我收到错误:“可访问性不一致:参数类型'frmPhoneDirectory.record[]”的可访问性低于方法'