我正在尝试比较四个阵列。四个数组中的两个存储文件名,而另外两个数组存储哈希码。
存储文件名的数组之一与存储哈希码的数组之一有关,这些哈希码用于文件名数组中的文件。
例如,我有两个项目ProjectOne
和ProjectTwo
。 ProjectOne
是名为ProjectOneFiles
的数组和ProjectOneHashcodes
数组的组合。这两个数组的长度始终相同。
ProjectTwo
将是一个名为ProjectTwoFiles
的数组和一个ProjectTwoHashcodes
数组的组合。这两个数组也总是具有相同的长度。
但ProjectOne
与ProjectTwo
的长度不一定相同。这就是我目前所拥有的:
private void Compare()
{
String[] ProjectOneFiles = ProjOneFiles();
String[] ProjectTwoFiles = ProjTwoFiles();
String[] ProjectOneHash = ProjOneHash();
String[] ProjectTwoHash = ProjTwoHash();
for (int x = 0; x < ProjectOneFiles.length; ++x)
{
String Test1 = ProjectOneFiles[x];
String Test2 = ProjectTwoFiles[x];
String Test3 = ProjectOneHash[x];
String Test4 = ProjectTwoHash[x];
if (Test1 != Test2)
{
listBox6.Items.Add(Test1);
listBox6.Items.Add(Test2);
}
else if ((Test1 == Test2) && (Test3 == Test4))
{
listBox7.Items.Add(Test1);
}
else
{
listBox8.Items.Add(Test1);
}
}
}
显然现在我的问题出现在四个数组中有两个长度不同的地方。如果我尝试迭代并且我使用最小的数组大小,因此我不会完全遍历最大的数组。
如果我尝试迭代一个数组,比方说有五个项目,那么显然我会超出范围异常。
我需要首先比较两个文件名数组,然后比较两个哈希码数组是否相同。如果他们满足某些要求,则需要将其列入三个列表中的一个,并且可能填写所有三个列表。
我本来希望在LINQ中完成它:
var onlyinfirst =
from s in ProjectOneFiles
where !ProjectTwoFiles.Contains(s) &&
(ProjectOneHash.Contains(p) == ProjectTwoHash.Contains(p))
select s;
var onlyinsecond =
from s in ProjectTwoFiles
where !ProjectOneFiles.Contains(s)
select s;
var onboth =
from s in ProjectOneFiles
where ProjectTwoFiles.Contains(s)
select s;
但是我这样做是因为我不确定如何使用嵌套语句删除我的if
语句。正如你在我的第一行中所看到的,我试图做到这一点,但我现在完全坚持使用它。文件名数组和哈希码数组都是相关的,因此LINQ语句必须在单个传递中,否则哈希码将不再与文件名相关联(索引方式)。
我的许多问题可以通过使用多维数组来解决,但我发现它们非常令人困惑,我宁愿不必重写我的函数来使用它们。
有助于解释的额外信息和功能:
如果有人需要此信息来帮助回答我的问题,那么文件名和数组就会从这样的XML文档中提取出来:
<?xml version="1.0" encoding="utf-8"?>
<Projects>
<Project Name="tfasdtyf">
<TestCycle Number="2387468">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest1.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-25" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="tfasdtyf">
<TestCycle Number="23423">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="Music">
<TestCycle Number="12312">
<Files>
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Shut Ya Mouth.mp3" />
<HashCode Code="3E-92-80-93-D5-64-19-16-26-8D-39-2A-C7-0B-C8-EB" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Snake Eater.mp3" />
<HashCode Code="8B-DF-19-AE-87-52-64-2E-85-CF-57-4B-85-4D-CC-E9" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Stuck in the System.mp3" />
<HashCode Code="6A-30-A7-53-FF-29-A5-DF-6D-24-DF-41-74-EE-06-4D" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Martin Solveig - Hello (Featuring Dragonette).mp3" />
<HashCode Code="93-90-A3-9C-BE-81-63-03-D7-96-1F-72-E4-ED-2D-32" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Stimming - Funkworm.mp3" />
<HashCode Code="8F-E1-7A-F1-B7-80-C6-2F-DC-34-FD-82-A0-DA-35-5E" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\1. Downlink - Ignition.mp3" />
<HashCode Code="3D-89-B3-C2-73-A6-A0-85-02-C0-B4-F9-C8-09-14-C7" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Psychedelic Runway.mp3" />
<HashCode Code="00-72-5C-CE-25-73-98-31-69-71-68-48-31-A1-A3-5A" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Rapture.mp3" />
<HashCode Code="1E-A6-53-07-10-FD-A3-4C-EF-D6-92-7F-CE-97-88-6E" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02_Digital-Controller.mp3" />
<HashCode Code="94-E0-CA-5F-2B-D2-56-7B-AF-2E-04-50-58-38-4D-B4" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\2. Downlink - Gamma Ray.mp3" />
<HashCode Code="3C-7A-76-AD-A6-2C-D1-7E-61-24-C0-40-BD-A7-A9-41" />
</Files>
</TestCycle>
</Project>
</Projects>
然后我有四个类似下面的函数来拉动项目的文件名和哈希码,这就是我得到每个数组的方式:
private String[] ProjOneFiles()
{
//Intialize the functions in the DLL
DllTest.Funtions Functions = new DllTest.Funtions();
//Set the location where the XMLs can be found
String Directory = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\";
//Get and set the number of items in the directory
int NumFiles = Functions.GetNumFiles(Directory);
//Create a search string to be used to determine the fullpath name of the file
//selected from the combobox
String SelectedFile = comboBox1.SelectedItem.ToString();
String SearchString = "*" + SelectedFile + "*.XML";
//Get and set the TC that will be used to get the filenames and hashcodes
int SelectedTC = int.Parse(comboBox2.SelectedItem.ToString());
//Get and set an array containing a full path structure to the item selected from
//the combobox using the search string created earlier. Get files returns an array
//thus needs to be stored in an array
String[] FullPaths = new String[NumFiles];
FullPaths = System.IO.Directory.GetFiles(
"C:\\Users\\brandonm\\Desktop\\Backup\\XML",
SearchString,
System.IO.SearchOption.AllDirectories);
int number = FullPaths.GetLength(0);
// The number of items in the XML ie. Number of Filenames in a particular TC
int NumXMLItems = NumXMLItemsListOne();
// Initialize the array that will hold the Filenames and their equivalent Hashcodes
String[] FileNames = new String[NumXMLItems];
int y = 0;
//Itteration through the all the XMLs in the location to add the current items into their arrays
for (int x = 0; x < NumFiles; x++)
{
String FullPath = FullPaths[x];
XPathNavigator Root = new XPathDocument(FullPath).CreateNavigator();
foreach (XPathNavigator Cycle in Root.Select(
String.Format(@"//TestCycle[@Number = '{0}']",
SelectedTC))
)
{
foreach (XPathNavigator Nav in Cycle.Select(@"Files/FileName/@File"))
{
FileNames[y] = Nav.Value;
//listBox4.Items.Add(Nav.Value);
y = y + 1;
}
}
}
return FileNames;
}
private String[] ProjOneHash()
{
//Intialize the functions in the DLL
DllTest.Funtions Functions = new DllTest.Funtions();
//Set the location where the XMLs can be found
String Directory = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\";
//Get and set the number of items in the directory
int NumFiles = Functions.GetNumFiles(Directory);
//Create a search string to be used to determine the fullpath name of the file
//selected from the combobox
String SelectedFile = comboBox1.SelectedItem.ToString();
String SearchString = "*" + SelectedFile + "*.XML";
//Get and set the TC that will be used to get the filenames and hashcodes
int SelectedTC = int.Parse(comboBox2.SelectedItem.ToString());
//Get and set an array containing a full path structure to the item selected from
//the combobox using the search string created earlier. Get files returns an array
//thus needs to be stored in an array
String[] FullPaths = new String[NumFiles];
FullPaths = System.IO.Directory.GetFiles(
"C:\\Users\\brandonm\\Desktop\\Backup\\XML",
SearchString,
System.IO.SearchOption.AllDirectories);
int number = FullPaths.GetLength(0);
// The number of items in the XML ie. Number of Filenames in a particular TC
int NumXMLItems = NumXMLItemsListOne();
// Initialize the array that will hold the Filenames and their equivalent Hashcodes
String[] HashCode = new String[NumXMLItems];
int z = 0;
//Itteration through the all the XMLs in the location to add the current items into their arrays
for (int x = 0; x < NumFiles; x++)
{
String FullPath = FullPaths[x];
XPathNavigator Root = new XPathDocument(FullPath).CreateNavigator();
foreach (XPathNavigator Cycle in Root.Select(
String.Format(@"//TestCycle[@Number = '{0}']",
SelectedTC))
)
{
foreach (XPathNavigator Nav in Cycle.Select(@"Files/HashCode/@Code"))
{
HashCode[z] = Nav.Value;
//listBox4.Items.Add(Nav.Value);
z = z + 1;
}
}
}
return HashCode;
}
答案 0 :(得分:3)
简单而不是特别优雅的方式:
private void Compare()
{
String[] ProjectOneFiles = ProjOneFiles();
String[] ProjectTwoFiles = ProjTwoFiles();
String[] ProjectOneHash = ProjOneHash();
String[] ProjectTwoHash = ProjTwoHash();
for (int x = 0; x < ProjectOneFiles.length || x < ProjectTwoFiles.length; ++x)
{
String Test1 = x < ProjectOneFiles.length ? ProjectOneFiles[x] : "";
String Test2 = x < ProjectTwoFiles.length ? ProjectTwoFiles[x] : "";
String Test3 = x < ProjectOneFiles.length ? ProjectOneHash[x] : "";
String Test4 = x < ProjectTwoFiles.length ? ProjectTwoHash[x] : "";
if (Test1.CompareTo(Test2) != 0)
{
listBox6.Items.Add(Test1);
listBox6.Items.Add(Test2);
}
else if (Test3.CompareTo(Test4) == 0)
{
listBox7.Items.Add(Test1);
}
else
{
listBox8.Items.Add(Test1);
}
}
}
答案 1 :(得分:1)
要详细说明上面提到的词典方法,你可能会考虑这样的事情: 字典hashDic = new Dictionary();
for(int i = 0; i < ProjectOneFiles.Length; i++)
{
//Add to the dictionary using hashDic.Add(FILENAME_HERE, HASH_HERE).
}
for(int i = 0; i < ProjectTwoFiles.Length; i++)
{
string projectOneValue;
if(hashDic.TryGetValue(ProjectTwoFiles[i], out projectOneValue))
{
//If this code executes, you'll know that the file is in both projects.
//The hash for the file in project one is in "projectOneValue."
//The hash for the file in project two is in "ProjectTwoHash[i]".
//You can remove this entry from the dictionary using
//hashDic.Remove(FILE_NAME_HERE)
}
else
{
//If this code executes, then this file is only in ProjectTwo.
}
}
//This loop will loop over all the files that are ONLY in ProjectOne.
foreach(KeyValuePair<string, string> kvp in hashDic)
{
//kvp.Key is the filename.
//kvp.Value is the hash.
//For every pass of this loop you'll be looking at a different
//file/hash that is ONLY in project one.
}
答案 2 :(得分:0)
不可否认,我最后跳过了一些内容,但这对你有用吗?
我不确定你到底陷入了困境,但似乎你只需要一只手来确定哪些物品是独一无二的,哪些物品并非每个列表都是唯一的。
在这种情况下,这应该有所帮助:
var onlyInListOne = ProjectOneFiles.Except(ProjectTwoFiles);
var onlyInListTwo = ProjectTwoFiles.Except(ProjectOneFiles);
var inBothLists = ProjectOneFiles.Intersect(ProjectTwoFiles);
我使用“var”关键字来保存输入,但是要从LINQ语句中吐出的实际数据类型是IEnumerable。如果你需要它作为List你可以在行的末尾调用.ToList(),如下所示:
var onlyInListOne = ProjectOneFiles.Except(ProjectTwoFiles).ToList();
var onlyInListTwo = ProjectTwoFiles.Except(ProjectOneFiles).ToList();
var inBothLists = ProjectOneFiles.Intersect(ProjectTwoFiles).ToList();
一般来说,虽然 - ToList()不是地球上最快的方法,所以虽然它有时是必要的,但如果你真的不需要List对象,我会避免它。
.Except(...)只接受一个列表中的所有字符串,并排除其他列表中的任何字符串。 .Intersect(...)只查找两个列表中的文件。
如果我错过了其他特别的内容,请在评论中告诉我,我会看看是否可以提供帮助。
答案 3 :(得分:0)
试试这个。
private void Compare()
{
String[] ProjectOneFiles = ProjOneFiles();
String[] ProjectTwoFiles = ProjTwoFiles();
String[] ProjectOneHash = ProjOneHash();
String[] ProjectTwoHash = ProjTwoHash();
//make project one the greater of the two always
if (ProjectTwoFiles.Length > ProjectTwoFiles.Length)
{
Swap(ref ProjectOneFiles, ref ProjectTwoFiles);
Swap(ref ProjectOneHash, ref ProjectTwoHash);
}
for (int x = 0; x < ProjectTwoFiles.length; x++)
{
String Test1 = ProjectOneFiles[x];
String Test2 = ProjectTwoFiles[x];
String Test3 = ProjectOneHash[x];
String Test4 = ProjectTwoHash[x];
if (Test1 != Test2)
{
listBox6.Items.Add(Test1);
listBox6.Items.Add(Test2);
}
else if ((Test1 == Test2) && (Test3 == Test4))
{
listBox7.Items.Add(Test1);
}
else
{
listBox8.Items.Add(Test1);
}
}
for (int x = ProjectTwoFiles.Length + 1; x < ProjectOneFiles.length; x++)
{
//add to some other list
}
}
private static void Swap(ref string[] foo, ref string[] bar)
{
string[] tmp = foo;
foo = bar;
bar = tmp;
}
诀窍是通过交换使ProjectOne成为更大的阵列。现在所有操作都很简单,因为您可以随时预测更大的阵列。
免责声明:这只是解决了您的问题。它根本没有优化。
可以从更改DevelopSomalia()
更改为DevelopCountry("Somalia")