C# Loop through Files and Repeat Until Every Combination of Comparisons is Complete
I have to perform a t开发者_高级运维ask and I'll do my best to detail it.
I have 5 folders, for example:
- Folder A
- Folder B
- Folder C
- Folder D
- Folder E
In each of these folders is a file. Basically, I need to compare each file against one another (I'll be calculating a value based upon data within these files.) This needs to be done for every combination (A to B, A to C, A to D, A to E, B to C, B to D, B to E, C to D, C to E, D to E)
Not really sure where to begin with this. Any help is greatly appreciated!
Something like this should work
var folders = new string[] { "A", "B", "C", "D", "E" };
for (int i = 0; i < folders.Length; i++)
{
for(int j = i+1; j < folders.Length; j++)
Console.WriteLine(folders[i] + "=>" + folders[j]);
}
Of course, I'm using a simple string[] for demonstration purposes but I hope you get the concept?
Let's assume you have the FileInfo
object for your files already, then you could do something like this:
List<FileInfo> files = new List<FileInfo>() {};
foreach (FileInfo fileContentA in files)
{
foreach (FileInfo fileContentB in files.Where(
x.Name.CompareTo(fileContentA.Name) > 0))
{
Compare(fileContentA, fileContentB);
}
}
string[] folder = { "A", "B", "C", "D", "E" };
for (int i=0; i<folder.Length; ++i)
for (int j=i+1; j<folder.Length; ++j)
compareFolders(folder[i], folder[j]);
You could create an extension method to encapsulate this algorithm for use with any array:
public static class Alg
{
public static void nonIdentityPermutations<T>(this T[] elements, Action<T, T> action)
{
for (int i=0; i<elements.Length; ++i)
for (int j=i+1; j<elements.Length; ++j)
action(elements[i], elements[j]);
}
}
Then you could write:
folder.nonIdentityPermutations( (a,b) => Console.WriteLine(a + " to " + b) );
or:
folder.nonIdentityPermutations(compareFolders);
Not sure what your returning value is, but here's an example of traversing the five folders and appending values to a single string as the final value.
You can build your own logic upon this.
string CompareMyFolders()
{
string FinalValue = "";
DirectoryInfo[] folders = new DirectoryInfo[5];
folders[0] = new DirectoryInfo("C:\\FolderA\\");
folders[1] = ...;
folders[2] = ...;
folders[3] = ...;
folders[4] = ...;
for(int i = 0; i < folders.Length - 1; i++)
for(int j = i + 1; j < folders.Length; j++)
FinalValue += CompareFolders(folders[i], folders[j]);
return FinalValue;
}
string CompareFolders(DirectoryInfo folder1, DirectoryInfo folder2)
{
string value = "";
// compare the files in both directory
// append the returning data to the value
return value;
}
I would suggest to start wit a comparison A to B, A to C, A to D, A to E. Then Go on with B to (C to E), then C to (D and E) and then the only one left is D to E.
How about something like:
var files = Directory.GetFiles(myDir, myExtension, SearchOption.AllDirectories)
.OrderBy(f => f)
.ToArray();
var comparisons = from file1 in files
from file2 in files
where StringComparer.Ordinal.Compare(file1, file2) < 0
select new {
file1,
file2,
Comparison = MyComparison(file1, file2)
};
Essentially, what this does is create a binary cartesian product of files
with itself, and then filters the tuples in a way that prevents both (A,B) and (B,A) from being selected.
Obviously, the sample code will have to be modified to meet your exact requirements.
One solution
#using system.io
private void RecurseFiles()
{
String[] files = Directory.GetFiles(@"c:\dev\", "*.tif", SearchOption.AllDirectories);
for (int i = 0; i < files.Length; i++)
for (int j = i+1; j < files.Length; j++)
CompareFiles(files[i], files[j]);
}
If you compare folders to identify mutually corresponding files, then you deal with 3 keys. 1st key is file name (or other means to identify correspondence of 2 files from different directories). 2nd key is directory (part of file's identity). 3rd key is content of the file (or part of content, or attributes, timestamps, hashes etc).
- gather all file identities as triplets of keys
- sort them in single container using keys 1,2,3 in this very order
- traverse the sorted container by taking subset of file identities by single key#1 value at a time.
- for each such subset build square table with empty diagonal and empty half, where sides of table are key 2,3 values of identities
- traverse the resulting triangle in any direction to fill the result table (of same shape) completely
- accumulate the resulting tables in some final container or keep pushing results to output
- repeat for next subset until there are no more subsets
- done
A nested loop would easily do the trick to ensure each file is compared to all the others. Not sure of the c# syntax, but this should give you the basic idea:
for each (file:File in fileArray)
{
for each (
Edit: Bah! I'm way too slow for this site. Anyone who beat me with an example of a nested loop gets a +1. =D
精彩评论