LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

I need to sort an array of strings based on the number in each string.

Basically, I have a directory of files that all have the same name but each with a different number on the end.

example: image 1.jpg, image 2.jpg, etc.

When I use the List Directory function that returns an array of strings containing the file names in the directory, they don't come out in a 1, 2, 3, order like they appear in the directory. It sorts them character by character so that they come out like: 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21, 22 etc.

Is there a simple way of sorting this array of strings with the file names (as above) so that they are in numerical order?
0 Kudos
Message 1 of 16
(10,669 Views)
"Is there a simple way of sorting this array of strings with the file names (as above) so that they are in numerical order?"

I will let you judge if it is simple.

First, the problem is that you are getting the files in alphabetical order. A quick solution would involve changing the naming convetion to use leading zeros for the number part of the file name. This will let your Op Sys do the sorting in the order you want. If you cannot change the naming convention, then read on.

In a for loop you will want to use string operators to pull the numeric part of the file names out of each file name. Convert these into a numerics and then pack these values into a cluster with two fields. The first cluster element MUST be the numeric. THe second should cantain the f
ile name, un-molested. Acumulate an array of these clusters in an array coming out of the for loop.

Pass this array of clusters into the "sort 1-d array". The Sort 1-d array function will sort clusters based on the first element of the cluster.

You can then take this sorted array of clusters into another for loop where you unbunlde the file name and once again accumulate the new array in an output tunnel.

DONE!

Simple? You tell me.

Ben

I feel obligated to acknowledge Rolf Kalbermatter of CIT Enginnering Nederland BV for this "cluster sort" technique. Rolf has been one of the largest contributors to "Info-LabVIEW" and has contributed greatly to the success of LV.
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 2 of 16
(10,667 Views)
That is perfect. Thank you.

I do have one more problem though, and I'm sure it is a simple thing, I just don't really know what I am doing. I can't quite seem to figure out a simple way of pulling the numeric part out. Well, I can do it if I know exactly what the "base" part of the file names is, ie. base 1.txt, base 2.txt, base 3.txt...

But I was hoping you could tell me how to get the numeric off the end if "base" was of an unknown length and could possibly contain numbers itself. The only guarantee on the file name is that it will end with a space, a number, period, and the extension.

I can use the Number To Decimal String function to read off the numeric and convert it to a number but this requires that I know exactly where the number starts and
I would like to be able to do this without knowing what the "base" part of the file name is (or how long) is. I tried reversing the order of the string thinking that then I know that the numeric I want begins in position 4. But then if it ends in any zeros, they become leading zeros when I reverse it and the Number To Decimal String function ignores those so that 1, 10, and 100 (ie. 1, 01, 001 in reverse) all come out as 1.

The other thing I tried seems to work but isn't very elegant. I took each file name and, inside a loop, concatenated an index (converted to a string) with a space at the beginning and a period at the end and used the Match function to see if it matched any part in the file name. If it didn't, the next iteration would concatenate the next index with the space and the period and search for that in the string and over and over until it found a match. Then I would know what the number was by which iteration it was on in the loop. This worked well enough, and i
t doesn't require a knowledge of the "base" part of the file name, but it is sort of a "brute force and ignorance" approach.

If you have any suggestions they would be greatly appreciated.

Thank you.
0 Kudos
Message 3 of 16
(10,667 Views)
Hi CJS

If the seed was known, I would say simple.

I believe this can be handled with the right formatting string, but I do not claim to be a hot dog at string formatting.

Post a new Q about this topic to LV-General to get better (and faster) answers than waiting for me.

Gotta run,

Ben

P.S. Make sure you provide examples that illustrate just what kind of string formats you want to work on.
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 4 of 16
(10,667 Views)
It's a while since this thread was started, but I am sure others will have use for this so here goes:
 
The in-built array sort function sorts the strings the same way DOS and Windows do. Microsoft has fixed this in the Explorer that comes with XP, however the rest of the OS(s) still sorts the old way.
 
The attached "AlphaLogical String Array Sort" VIs will sort strings arrays the same way as the new XP Explorer. There are three different implementations of the sorting, one based on the Insertion sort algorithm, a Quick Sort based on recursive calls (the most elegant way, but unfortunately LabVIEW has too much overhead when doing recursive calls so this is actually a very slow alternative) and finally the fastest; a stack based Quick Sort. There is also a test VI that will show you how the different implementations perform.
 
I had not used recursive calls in LV much until I made the attached quick sort and was a bit disappointed by the fact that it is so slow, but it's a good learning example...The ability to do recursive calls this way was introduced in LV7 I believe...There is an example here on the zone that shows how you can calulate a factorial by using recursive calls, however - unlike for the quick sort (normally) - recursive calls are actually not the optimal solution for that calculation.

Message Edited by Mads on 09-13-2005 02:30 AM

Message 5 of 16
(10,497 Views)
I can't open your file because I use 7.0, but try changing the recursive part to use queues if it used the build array method.
0 Kudos
Message 6 of 16
(10,485 Views)
Hi UnclebumpSmiley Wink
 
Attached are the files in 7.0 format.
 
The recursive call does not need to build arrays (the sorting is an in-place version to keep the memory requirement to a minimum), it is the recursive calls themselves that make the recursive version slow.
Message 7 of 16
(10,479 Views)

Very good Ben "Knight of NI"!

You described it perfectly!

Thanks a lot!

Message 8 of 16
(6,373 Views)

@praveen193380 wrote:

Very good Ben "Knight of NI"!

You described it perfectly!

Thanks a lot!


So, give him a kudo!

Message 9 of 16
(6,354 Views)

@cjs  a écrit :
That is perfect. Thank you.

I do have one more problem though, and I'm sure it is a simple thing, I just don't really know what I am doing. I can't quite seem to figure out a simple way of pulling the numeric part out. Well, I can do it if I know exactly what the "base" part of the file names is, ie. base 1.txt, base 2.txt, base 3.txt...

But I was hoping you could tell me how to get the numeric off the end if "base" was of an unknown length and could possibly contain numbers itself. The only guarantee on the file name is that it will end with a space, a number, period, and the extension.

I can use the Number To Decimal String function to read off the numeric and convert it to a number but this requires that I know exactly where the number starts and
I would like to be able to do this without knowing what the "base" part of the file name is (or how long) is. I tried reversing the order of the string thinking that then I know that the numeric I want begins in position 4. But then if it ends in any zeros, they become leading zeros when I reverse it and the Number To Decimal String function ignores those so that 1, 10, and 100 (ie. 1, 01, 001 in reverse) all come out as 1.

The other thing I tried seems to work but isn't very elegant. I took each file name and, inside a loop, concatenated an index (converted to a string) with a space at the beginning and a period at the end and used the Match function to see if it matched any part in the file name. If it didn't, the next iteration would concatenate the next index with the space and the period and search for that in the string and over and over until it found a match. Then I would know what the number was by which iteration it was on in the loop. This worked well enough, and i
t doesn't require a knowledge of the "base" part of the file name, but it is sort of a "brute force and ignorance" approach.

If you have any suggestions they would be greatly appreciated.

Thank you.

You can use a regular expression to extract the number. In the following code the top loop uses the method describe by Ben using the cluster sort. The bottom loop find the file number using a similar regex, convert the number to have 4 digits with leading zeros, replace the original number by this 4 disgits one and the sort the resulting array.

 

Both methods works and have their advantages/desavantages. The first one you need to unbundle to get the filenames, the second one changes the filename a bit.

 

Note, the left loop is just use to generate random number filenames and duplicate names are highly probable.

 

Sort Filenames.png

 

Ben64

Message 10 of 16
(6,329 Views)