Alphabetizing string array

So I have a few Strings. These strings very in length but are always ascii characters.
ABDF
BGA
DQW
ATG 1

How do I put them into a bubble array to alphabetize them? They need to stay Strings as this program talks to other programs already waiting for them. I can make a char or int array but can't seem to figure out how to make it apply to strings

Can you give a small sketch, that shows the problem and that we can try ?

Do you really want to use the String object ?

Perhaps the compareTo() can be used. It seems to work as the normal string compare. Try it.

No one talks to others with the String object. I think that is impossible. Sooner or later it is converted to a bunch of characters in an array.

What is a “a bubble array”?

sounds like you want to create a array of pointers to Strings or c-strings and use a bubble sort to sort the array of pointers.

the compare routine will have to find the character not in common with both String/c-strings and compare that character

Koepel:
Can you give a small sketch, that shows the problem and that we can try ?

Not really as everything I have tried failed miserably!

Koepel:
Do you really want to use the String object ?

Yes, I do... Or I should say, I don't know how else to do it... This is on a receiver that has data from many other transmitters. They all send their data and as the receiver gets the packets, it saves them as Strings in order to receive the next data dump. After 5 seconds, it prints all the data collected to an I2C display. In these 5 seconds, each transmitter will send two packets (to ensure no complete data loss. well technically way more than that ignore the retries... But two different times if the network is busy or range is getting to limits). If a second packet is received, it overwrites the first. That way when it prints to the Nextion, there are no duplicates even if the values of the sensors do change.
Example of data returned
Red Team GO
Blue Team STOP
Yellow Team GO NORTH
Yellow Team STOP
Green Team 3 yards to the EAST
....
Right now as this data comes in, the receiver is only receiving and not doing a handshake with each transmitter. I was having issues with the transmitters keep a lock on the SPI sensors it was doing as I am using Nrf24L01 transmitters that also are using SPI. So it switching between two SPI's... I decided to just collect the data it needed and send it away after collection. Because of this, the data comes in each time but not always in order. To keep the screen from moving names around, I want to put them in order...
Blue
Green
Red
Yellow
I will play with the compareTo() but I will have up to 15 different data packet dumps, so this might not be very feasible.
Red, Green, Blue, Orange, Teal, Yellow, Black, Brown, Purple, Gold, Silver, Pink, Gray, White, Tan....

gcjr:
sounds like you want to create a array of pointers to Strings or c-strings and use a bubble sort to sort the array of pointers.

the compare routine will have to find the character not in common with both String/c-strings and compare that character

Do you know of an Arduino example for this? The only one I could find was with using a single char or int.

Why not sort the data as the packets come in? Meaning put each new string in its proper place as soon as you receive it rather than receiving them all first then sorting.

Also, perhaps you could come up with some numeric code for each message so the packets wouldn't be so verbose.

Can you find out the sorting order of.. 2 strings?

-jim lee

gfvalvo:
Why not sort the data as the packets come in?

I don't know what is coming in at any given dump. No idea how I would go about this. Do you have an idea I could chase?

jimLee:
Can you find out the sorting order of.. 2 strings?

-jim lee

Not really. I could use compareTo() for two but when I have 15 different packets coming in, I don't think that would work

Well.. If you have a list of strings.. And can compare at least two.. And maybe swap these two if need be. You basically have all the LEGOS you need.

-jim lee

pelicansparky:
I don't know what is coming in at any given dump. No idea how I would go about this. Do you have an idea I could chase?

Presumably, your processor receives the packets one at a time. So, build your sorted list / array on-the-fly. Each time a new packet arrives scan through the existing list and determine where it belongs based on your sorting criteria. Insert it there and wait for the next packet.

Using classes and libraries…

#include <lists.h>
#include <resizeBuff.h>


//**************************************************************
//  Setting up a linked list of strings that can be sorted.. 
//  First is the list object that holds the string info. and
//  can compare itself to another string object..
//**************************************************************

String myString;     // These two are for doing the compare. They are globals.
String theirString;


// The class setup for the list object.
class stringObj : public linkListObj {
   public:
                  stringObj(char* inStr);
   virtual        ~stringObj(void);

   virtual  bool   isGreaterThan(linkListObj* compObj);   // Are we greater than the obj being passed in? Primary sorting function.
   virtual  bool   isLessThan(linkListObj* compObj);      // Are we less than the obj being passed in? Primary sorting function.

            char* mStr;
};

// Now the code we add to the class..
stringObj::stringObj(char* inStr)
   : linkListObj() {

   mStr = NULL;                              // Defualt our dynamic memory pointer to NULL
   if (resizeBuff(strlen(inStr)+1,&mStr)) {  // IF we were able to allocate enough RAM for holding our string..
      strcpy(mStr,inStr);                    // Stuff a copy of what we got into our object.
   }
}


// Recycle the RAM we used.
stringObj::~stringObj(void)  { resizeBuff(0,&mStr); }
 

// Are we greater than the obj being passed in? Primary sorting function.
bool stringObj::isGreaterThan(linkListObj* compObj) {
      
      stringObj* them;
      
      them = (stringObj*)compObj;      // We get a pointer to a linkListObj. We know its a stringObj. Just say it is.
      myString = mStr;                 // Load up the gloabl String, myString with our string.
      theirString = them->mStr;        // Load up the gloabl String, theirString with the incoming object's string.
      return myString>theirString;     // Return the result of the compare.
}


// Are we less than the obj being passed in? Primary sorting function.
bool stringObj::isLessThan(linkListObj* compObj) {      

   stringObj* them;
   
   them = (stringObj*)compObj;      // We get a pointer to a linkListObj. We know its a stringObj. Just say it is.
   myString = mStr;                 // Load up the gloabl String, myString with our string.
   theirString = them->mStr;        // Load up the gloabl String, theirString with the incoming object's string.
   return myString<theirString;     // Return the result of the compare.
}


//**************************************************************
// That's all for the string list object. Now we code up the 
// changes that make our stringList..
//**************************************************************


// Class setup for our stringList
class stringList :   public linkList {

  public:
                  stringList(void);
   virtual        ~stringList(void);

                  void addString(String* inStr);
                  void addString(char* inStr);
                  void printStrings(void);
};


// Constructor, nothing to do..
stringList::stringList(void)
   : linkList() {  }


// Destructor, nothing to do..  
stringList::~stringList(void) {  }


// Add in a String object. We use a pointer and call the c string addString() method with that.
void stringList::addString(String* inStr) { addString(inStr->c_str()); }

// Here's where we actually add the string to the list.
void stringList::addString(char* inStr) {

   stringObj*  newItem;

   newItem = new stringObj(inStr);  // Create the new list node with the incoming c string.
   addToTop(newItem);               // Stick it in the list, anywhere will do. Top is fastest.
}


// Sort and print all our strings to the serial monitor.
void stringList::printStrings(void) {

   stringObj* trace;
   
   sort(true);
   trace = (stringObj*)getFirst();
   while(trace) {
      Serial.println(trace->mStr);
      trace = (stringObj*)trace->getNext();
   }
}


// ***********************************************
// The main program..
// ***********************************************


stringList aStringList;   // An instance of the stringList class we created above.

String aString("The floppy fish");   // We have a (gasp) string object.

void setup(void) {

   Serial.begin(57600);
   aStringList.addString("Hello!");                // Add in a string or 4..
   aStringList.addString("My!");
   aStringList.addString("Aren't we all happy");
   aStringList.addString("Today?");
   aStringList.printStrings();                     // Lets see them sorted.
   Serial.println();
   aStringList.dumpList();                         // This dumps out all the strings and recycles the RAM.
   aStringList.addString("But wait!");
   aStringList.addString("Small frogs");
   aStringList.addString("Are jumping all over");
   aStringList.addString(&aString);                // <<-- String objects have to be passed in like this.
   aStringList.addString("In the pool.");
   aStringList.printStrings();                     // Lets see them sorted.
}


void loop(void) {}

If this isn’t too bizarre and you want to try it, install LC_baseTools from your library manager.

-jim lee

jimLee:
If this isn't too bizarre and you want to try it, install LC_baseTools from your library manager.

-jim lee

lol, well it's bizarre for sure! I'm totally lost but I'm willing to try anything. Thank much for that, I will get a good chance to dive in tomorrow to see if I can get it to work.

I took the .compareTo() function and build a sketch around it.

// Sort Arduino String objects according to their text.
// There are two ways:
//    Exchange the text inside the object or use pointers.
//
//


// Warning
//   This is not an array of texts.
//   This is an array of String objects, and each object
//   has a text assigned to it, which is stored in the String object.

#define NUM_STRINGS 18
String myStrings[NUM_STRINGS] = 
{ 
  "Hello there.",
  "Test 123",
  "Test",
  __DATE__ " " __TIME__ ,
  "01234567890123456789012345678901234567890.",
  "01234567890123456789012345678901234567890",
  "lower case 1",
  "lower case 0",
  "±3² + ½ * 5 = UTF-8 characters",
  "9",
  " space in front",
  "",    // empty textstring !
  "Red Team GO",
  "Blue Team STOP",
  "Yellow Team GO NORTH",
  "Yellow Team STOP",
  "Green Team 3 yards to the EAST",
  "blue team in lower case.",
};


void setup()
{
  Serial.begin( 9600);

  Serial.println();
  Serial.println();
  Serial.println();
  Serial.println( "-------------------------------------------------");
  Serial.println( "The text of the objects is:");
  for( int i=0; i<NUM_STRINGS; i++)
  {
    Serial.print( "  ");
    if( i<10)
      Serial.print( " ");
    Serial.print( i);
    Serial.print( ": ");
    Serial.println( myStrings[i]);
  }
  Serial.println();
  Serial.println( "Sorting the String objects according to the text:");
  sort( myStrings, NUM_STRINGS);
  for( int i=0; i<NUM_STRINGS; i++)
  {
    Serial.print( "  ");
    if( i<10)
      Serial.print( " ");
    Serial.print( i);
    Serial.print( ": ");
    Serial.println( myStrings[i]);
  }
  Serial.println( "-------------------------------------------------");
}


void loop()
{
  
}


void sort( String *p, int n)
{
  // Very simple sort.
  // Find the lowest, and put it the first location,
  // Then find the lowest of the remaining and put it in the second location.
  // And so on.

  if( n > 1)     // When there is one String object, then there is no sorting to do.
  {
    for( int i=0; i<n; i++)
    {
      for( int j=i+1; j<n; j++)
      {
        if( p[i].compareTo( p[j]) > 0)
        {
          // The new (higher index) object has lower text.
          // Put the new one in the place of the first one.
          String q = p[i];
          p[i] = p[j];
          p[j] = q;
        }
      }
    }
  }
}

I can probably just do a compare with two String objects. Well, at least the .compareTo() is working.

[Update] The ‘<’ can be used, because the String class handles that.
So this is the way to compare String objects and move the text around until they are sorted:

// Sort Arduino String objects according to their text.
// There is more than one ways
//    Exchange the text inside the object.
//    Copy text from one object to the other.
//    Use pointers to the String objects.
//
// I copy the text between objects, using the '=' from the class itself.
// To compare the texts of the objects, I use the '<' from the class itself.
//


// Warning
//   This is not an array of texts.
//   This is an array of String objects, and each object
//   has a text assigned to it, which is stored in the String object.

#define NUM_STRINGS 18
String myStrings[NUM_STRINGS] = 
{ 
  "Hello there.",
  "Test 123",
  "Test",
  __DATE__ " " __TIME__ ,
  "01234567890123456789012345678901234567890.",
  "01234567890123456789012345678901234567890",
  "lower case 1",
  "lower case 0",
  "±3² + ½ * 5 = UTF-8 characters",
  "9",
  " space in front",
  "",    // empty textstring !
  "Red Team GO",
  "Blue Team STOP",
  "Yellow Team GO NORTH",
  "Yellow Team STOP",
  "Green Team 3 yards to the EAST",
  "blue team in lower case.",
};


void setup()
{
  Serial.begin( 9600);

  Serial.println();
  Serial.println();
  Serial.println();
  Serial.println( "-------------------------------------------------");
  Serial.println( "The text of the objects is:");
  for( int i=0; i<NUM_STRINGS; i++)
  {
    Serial.print( "  ");
    if( i<10)
      Serial.print( " ");
    Serial.print( i);
    Serial.print( ": ");
    Serial.println( myStrings[i]);
  }
  Serial.println();
  Serial.println( "Sorting the String objects according to the text:");
  sort( myStrings, NUM_STRINGS);
  for( int i=0; i<NUM_STRINGS; i++)
  {
    Serial.print( "  ");
    if( i<10)
      Serial.print( " ");
    Serial.print( i);
    Serial.print( ": ");
    Serial.println( myStrings[i]);
  }
  Serial.println( "-------------------------------------------------");
}


void loop()
{
}


void sort( String *p, int n)
{
  // Very simple sort.
  // Find the lowest, and put it the first location,
  // Then find the lowest of the remaining and put it in the second location.
  // And so on.

  if( n > 1)     // When there is one String object, then there is no sorting to do.
  {
    for( int i=0; i<n; i++)
    {
      for( int j=i+1; j<n; j++)
      {
        if( p[j] < p[i])   // compare the text of one String object to text of another.
        {
          // The new (higher index) object has lower text.
          // Put the new one in the place of the first one.
          String q = p[i];
          p[i] = p[j];
          p[j] = q;
        }
      }
    }
  }
}

Are there literally only 15 different messages?

Perhaps with some data attached, but defined and unique and invariant for the first N characters?

Why do any sorting? All you need to do is to keep track of which messages are currently meaningful, and publish those in a predetermined order.

An array that tracks current message of interest.

Another to allow choosing a publishing mechanism either data driven or functionally as needed.

But hey, maintaining linked lists of strings (or Strings) on an Arduino sounds like fun!

a7

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.