Click to See Complete Forum and Search --> : Sorting one list to be the same as another.


TheDarklord
March 12th, 2010, 07:13 AM
I have some code which searches for files and adds them to a list based on the individual filenames. Then it sorts out if there are any duplicate files based on the filename.

For example:
Song: "Bat out of hell" in folder one is the same as Song "Bat out of Hell" in folder two.

The code also adds files to another list called filelist2 on based on the file extension.

For example "C:My Documents\Music\Folder 1: Bat out of Hell.mp3" and "C:My Documents\Music\Folder 2: Bat out of Hell.mp3".

In this case, the filename extension is not the same because "folder 1" and "folder2 are not the same.


foreach (string foldername in Directory.GetDirectories(DirectoryName))
{
MP3Header mp3hdr = new MP3Header();
string Mp3Filename;



foreach (string filename in Directory.GetFiles(foldername))
{
string extension = Path.GetExtension(filename);
FileInfo f = new FileInfo(filename);


if (extension == FileTypeExtension)
{
this.listBox1.Items.Add(filename);
}


if (f.Length <= thisFileLength)
{
this.listBox2.Items.Add(filename);

}

// Form1 tag = new Form1();

bool boolIsMP3 = mp3hdr.ReadMP3Information(filename);

this.listBoxFileName.Items.Add(mp3hdr.strFileName);
this.listBox3.Items.Add(mp3hdr.lngFileSize.ToString());
this.listBoxBitRate.Items.Add(mp3hdr.intBitRate.ToString());
this.listBoxFrequency.Items.Add(mp3hdr.intFrequency.ToString());
this.listBoxstrMode.Items.Add(mp3hdr.strMode);
this.listBoxstrLength.Items.Add(mp3hdr.strLengthFormatted);

//Mp3Filename = filename;

Filelist.Add(mp3hdr.strFileName);
Filelist2.Add(filename);
//Filelist.Add(filename);

Filelist.Sort();
Filelist2.Sort();




}
}
for (int i = 1; i <= Filelist.Count - 1; i++)
{

if (Filelist[i].ToString() == Filelist[i - 1].ToString())
{
this.listBox4.Items.Add(Filelist[i].ToString());
this.listBox5.Items.Add(Filelist[i-1].ToString());
}
}

}



Is there any way of sorting filelist2 to be the same order as filelist1?

For example:

In flielist one:
1. Bat out of Hell
2. Bat out of Hell
3. Like a virgin
4. Like a virgin.
5. Born to run.
6. Born to run.

Then in filelist2
1. C:My Documents\Music\Folder1\Bat out of Hell
2. C:My Documents\Music\Folder2\Bat out of Hell
3. C:My Documents\Music\Folder1\Like a virgin
4. C:My Documents\Music\Folder2\Like a virgin.
5. C:My Documents\Music\Folder1\Born to run.
6. C:My Documents\Music\Folder2\Born to run.

TheDarklord
March 12th, 2010, 12:22 PM
Is there any way I can sort the two lists like this sample code with arrays?


String[] animals = {"Zebra","Kiwi","Amazona Parrot","Tiger"};
String[] places = {"Africa","New Zealand","Jamaica","India"};
Array.Sort(animals,places);
foreach(String item in animals)
{
Console.WriteLine(item);
}
Console.WriteLine();
foreach(String item in places)
{
Console.WriteLine(item);
}


The output of this code is:

Amazona Parrot
Kiwi
Tiger
Zebra

Jamaica
New Zealand
India
Africa

TheGreatCthulhu
March 13th, 2010, 04:30 PM
First, you should know that Array.Sort(Array, Array) sorts the second array using the values of the first one as keys. The idea is to connect each value of the first array with the corresponding value of the second (the corresponding values being the ones with the same index), then sort the first array, and then reorganize the second based on the new order of the keys.

Note that the two arrays must have the same size.

Second, both of your lists are storing names from the same folder - so, the order is right until you sort your lists just after you add the names. Delete that code, and use Array.Sort(Array, Array) after all the names are added and after the loop ended.

TheDarklord
March 14th, 2010, 03:02 PM
It might sound like a silly question, but would I need to change the 'Filelist' and 'FileList2' to arrays in order for the sort.(filelist, filelist2) to work?

At the moment they're declared as;

List<string> Filelist = new List<string>();
List<string> Filelist2 = new List<string>();


Which works fine for methods like


Filelist.Add(mp3hdr.strFileName);
Filelist2.Add(filename);

Filelist.Sort();


and for the loop method

for (int i = 1; i <= Filelist.Count - 1; i++)
{

if (Filelist[i].ToString() == Filelist[i - 1].ToString())
{
this.listBox4.Items.Add(Filelist2[i].ToString());
this.listBox5.Items.Add(Filelist2[i-1].ToString());
}
}



How would I declare the sort.(flielist, filelist2) method?

I tried it as List<string>.Sort(Filelist,Filelist2);, it came back with the error "No overload for method 'Sort' takes '2' arguments".

TheGreatCthulhu
March 14th, 2010, 08:29 PM
The Sort method is a static method of the Array class, not a member method of List<T>, so you have to use Array.Sort(...) to call it - like you've done in the animals/places example.

I don't think it will work for lists - try it yourself, but even if it doesn't, after you've done adding your strings, call the ToArray() member method of the List<T> generic class to obtain a String[].

Do this for both of your lists, and store the arrays in variables. After that, you can use them with the Array.Sort(Array, Array) method.

So:

string[] files1 = filelist1.ToArray();
string[] files2 = filelist2.ToArray();
Array.Sort(files1, files2);

// use files1 and files2 to populate your list boxes.


There's an alternate approach, but I suggest that you at least try to get this to work first, since you'll be able to learn from the experience.
As for the alternate approach - you could use the SortedList<KeyType, ValueType> class; declare with SortedList<string, string>, use the Add(string, string) method of this class to add the file name and path at the same time, and in that order. The list will be sorted automatically. You can get the file names using the Keys property, and the paths using the Values property.

P.S. This is your own free choice, but

for (int i = 1; i <= Filelist.Count - 1; i++)

is usually written as

for (int i = 1; i < Filelist.Count; i++).