我有三个System.Array,我基本上存储了10个字符的电话号码。定义如下:
private static System.Array objRowAValues;
private static System.Array objRowBValues;
private static System.Array objRowCValues;
我这样做是因为我读了一个包含许多单元格(大约1 000 000)的巨大Excel文件,并且使用List<string>
的进程有点慢。稍后在我的代码中,我将System.Array更改为List<string>
,主要是因为我填充了ListBox元素。这些是List
private List<string> bd = new List<string>();
private List<string> bl = new List<string>();
private List<string> cm = new List<string>();
我想检查objRowBalues或objRowCValues中是否存在objRowAValues中的任何值,如果存在则删除现有值,我该怎么做?我是C#的新手,这是我的第一步。
编辑:这是我正在做的代码(仅限相关部分):
private List<string> bd = new List<string>();
private static System.Array objRowAValues;
private List<string> bl = new List<string>();
private static System.Array objRowBValues;
private List<string> cm = new List<string>();
private static System.Array objRowCValues;
private List<string> pl = new List<string>();
private static Microsoft.Office.Interop.Excel.Application appExcel;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range rngARowLast, rngBRowLast, rngCRowLast;
long lastACell, lastBCell, lastCCell, fullRow;
// this is the main method I use to load all three Excel files and fill System.Array and then convert to List<string>
private void btnCargarExcel_Click(object sender, EventArgs e)
{
if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (System.IO.File.Exists(openFileDialog1.FileName))
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
filePath.Text = openFileDialog1.FileName.ToString();
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(openFileDialog1.FileName, 0, true, 5, "", "", true,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false,
false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet) xlWorkBook.Worksheets.get_Item(1);
fullRow = xlWorkSheet.Rows.Count;
lastACell = xlWorkSheet.Cells[fullRow, 1].End(Excel.XlDirection.xlUp).Row;
rngARowLast = xlWorkSheet.get_Range("A1", "A" + lastACell);
objRowAValues = (System.Array) rngARowLast.Cells.Value;
foreach (object elem in objRowAValues) { bd.Add(cleanString(elem.ToString(), 10)); }
nrosProcesados.Text = bd.Count().ToString();
listBox1.DataSource = bd;
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
executiontime.Text =
String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds/10).ToString();
}
else
{
MessageBox.Show("No se pudo abrir el fichero!");
System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel);
appExcel = null;
System.Windows.Forms.Application.Exit();
}
}
}
// This is the method where I clean the existent values from bd (the List where I should remove existent values on bl and existent values on cm
private void btnClean_Click(object sender, EventArgs e)
{
pl = bd;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
pl.RemoveAll(element => bl.Contains((element)));
pl.RemoveAll(element => cm.Contains((element)));
textBox2.Text = pl.Count.ToString();
listBox4.DataSource = pl;
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
textBox6.Text =
String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10).ToString();
}
答案 0 :(得分:1)
实际上有两个问题:
对于第一个,我建议使用HashSet
作为Contains
操作,因为List
/ Array
需要O(1)而不是O(n)。
第二个有点棘手 - 而不是迭代第一个集合,你可以遍历其余部分,只是尝试从第一个集合中删除这些项目。
如果是Hashset
,则Remove
包含Contains
逻辑并返回bool
以指示值是否在收集中,因此使用HashSet
更容易第一集也。
所以看起来应该是这样的:
var a = new HashSet<string>();
// OR, if you have existing array:
// var a = new HashSet<string>(myArray);
var b = new HashSet<string>();
var c = new HashSet<string>();
// ... some filling logic here ...
foreach (var item in b)
{
a.Remove(item);
}
foreach (var item in c)
{
a.Remove(item);
}
之后,您可以使用ToList()
将值绑定到控件 - 它将创建包含所有未删除值的新数组:
List<string> aList = a.ToList();
答案 1 :(得分:0)
根据对OP的评论,以下是您想要做的事情:
...make your lists...
bd.removeAll(phoneNum => bl.contains(phoneNum) || cm.contains(phoneNum));
请注意,不应使用arrays
。您应该而是使用List<string>
来完成上述所有这三项操作。
答案 2 :(得分:0)
假设它们是List并且您只想在bd
中丢弃元素,因为您没有清楚地说明应删除哪些列表,我会这样做:
bd.RemoveAll(element => bl.Contains((element)));
bd.RemoveAll(element => cm.Contains((element)));
或者您可以尝试使用HashSet
private List<string> hsA = new List<string>();
private List<string> hsB = new List<string>();
private List<string> hsC = new List<string>();
尝试使用相同的方法:
hsA.RemoveWhere(element => hsB.Contains(element) || hsC.Contains(element));
答案 3 :(得分:0)
首先,如果您知道有多少行尝试使用适当的最大大小初始化List。所以它不必不断调整底层数组的大小。或者使用类型保存数组string[]
来节省铸造等方面的麻烦。
如果您想过滤RowAValues列表,可以使用Linq:
rowAValues = rowAValues.Where(x => !rowBValues.Contains(x)
&& !rowCValues.Contains(x))
.ToArray()
如果您使用的是课程列表,请将ToArray替换为ToList。
请记住,迭代数千个项目是非常高性能的。如果多次执行检查,请考虑对行b + c使用HashSet<string>
。代码保持不变,但查找速度很快。
LINQ(语言集成查询)的一个很好的参考是http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b