+ Start a Discussion
tfoiltfoil 

Sorting string like a summary

Hello all,

 

 

I've been trying to sort a list of strings like a summary but I have no idea about what to try now.

 

There is my problem:

 

I have string that represents positions in a summary, example: "1", '1.1", "1.1.1", "1.1.2", etc.

 

And I want to sort those in order like a structured things in the Microsoft project.

 

But for strings, "4" is not greater than "1.1". So things won't be in correctly order.

 

Searching in Google and here I tried to make a Wrapper. That looks like this:

 

global class PacoteWrapper implements Comparable {

public Pacote__c pac;

public PacoteWrapper(Pacote__c pc) {
pac = pc;
}

global Integer compareTo(Object compareTo) {

PacoteWrapper compareToPac = (PacoteWrapper)compareTo;

Integer returnValue = 0;

Double posDouble = Double.valueOf(pac.Posicao_EDT__c);
Double posCompareDoulb = Double.valueOf(compareToPac.pac.Posicao_EDT__c);

if (posDouble > posCompareDoulb) {
returnValue = 1;
} else if (posDouble < posCompareDoulb) {
returnValue = -1;
}

return returnValue;
}

 

 

And i use pacWrapperList.sort() to make things works.

 

But it will only works if my string is not greater than 2 dots. 

 

That means, it works great for strings like "1", "1.2", "2.3", etc.

 

It will fail for strings using 2 dots, of course. There is no double number with 2 dots, hahaha.

 

So, if anyone has a tip or a piece of code that can help me, i will be very glad.

 

Thank you all for attention. Best regards!

Best Answer chosen by Admin (Salesforce Developers) 
tfoiltfoil

Thank you all. Here is the solution.

 

Some comments and variable names are in Brazilian Portuguese, sorry for that.

 

global class PacoteWrapper implements Comparable {

public Pacote__c pac;

public PacoteWrapper(Pacote__c pc) {
pac = pc;
}

global Integer compareTo(Object compareTo) {

PacoteWrapper compareToPac = (PacoteWrapper)compareTo;

Integer returnValue = 0;

// Ordenando arrays de inteiros
// Lista A
Integer[] ListA = new Integer[]{};
if(pac.Posicao_EDT__c != null)
{
if(pac.Posicao_EDT__c.contains('.')){
for(string a : pac.Posicao_EDT__c.split('\\.')){
ListA.add(Integer.Valueof(a));
}
}
else
{
ListA.add(Integer.Valueof(pac.Posicao_EDT__c));
}
}

// Lista B
Integer[] ListB = new Integer[]{};
if(compareToPac.pac.Posicao_EDT__c != null)
{
if(compareToPac.pac.Posicao_EDT__c.contains('.')){
for(string b : compareToPac.pac.Posicao_EDT__c.split('\\.')){
ListB.add(Integer.Valueof(b));
}
}
else
{
ListB.add(Integer.Valueof(compareToPac.pac.Posicao_EDT__c));
}
}

//Se o tamanho dos Arrays for diferente, faz os doi arrays terem o mesmo tamanho, completando com zero
if(ListB.size() != ListA.size()){

Integer diferenca = 0;

if(ListA.size() > ListB.size()){
diferenca = ListA.size() - ListB.size();
for(Integer i =0; i < diferenca; i++){
ListB.add(0);
}
}else{
diferenca = ListB.size() - ListA.size();
for(Integer i =0; i < diferenca; i++){
ListA.add(0);
}
}
}

Integer index = 0;
while (index < ListA.size()) {

if (ListA[index] > ListB[index]) {
return 1;
} else if (ListA[index] < ListB[index]) {
return -1;
}

index++;
}

return returnValue;
}
}

All Answers

cduncombe44cduncombe44

What if you replace all the dots with spaces, or an A, or whatever.  Then you can sort the strings correctly, and then replace them all back again with the dots.

 

You could use ReplaceAll('string', 'replacement string') for this.

Jia HuJia Hu
try this

List<String> strlist = new String[]{'2.4', '2.3', '2.3.2', '1.1.1', '1.1.1.1'};
strlist.sort();
for(integer i = 0; i < strlist.size(); i++) {
System.debug( strlist[i] );
}

result:
07:02:06.033 (33922000)|USER_DEBUG|[4]|DEBUG|1.1.1
07:02:06.033 (33978000)|USER_DEBUG|[4]|DEBUG|1.1.1.1
07:02:06.034 (34021000)|USER_DEBUG|[4]|DEBUG|2.3
07:02:06.034 (34063000)|USER_DEBUG|[4]|DEBUG|2.3.2
07:02:06.034 (34103000)|USER_DEBUG|[4]|DEBUG|2.4
tfoiltfoil

It works! Thank you very much cduncombe44!

 

I put an 'A' instead of dots. Great! Tyvm again!

tfoiltfoil

Your way should work too, but i dont have only a Array of strings, i have a list of custom objects and i want to sort it by a string attribute. But thank you anyways, the first guy's sugestions worked for me anyways. But thank you very much Jia Hu.

tomcollinstomcollins

This is an ugly problem.  I just tried a few things and couldn't come up with a clean solution.

 

If your numbers are only single digits, you're typically OK.  '1.1' sorts after '1', and '4' sorts after both.  But, '10' sorts after '1.1' and before '2'.

 

One possibility would be to split your strings on '\\.' (using the String split method) and store a list of integers in your PacoteWrapper class instead of the actual strings.

 

In your comparison routine, start at index 0 of each list.  The logic will go something like this:

 

while (1) {

    if (index >= size of list A)

        if (index >= size of list B)

            return strings equal

        else

            return "string A comes before string B"

    else if (index >= size of list B || B[index] < A[index])

        return "string B comes before string A"

    else if A[index] < B[index]

        return "string A comes before string B"

 

    increment index

}

 

Once your list of wrapper objects are sorted, you need to convert each back to a string.  Unfortunately, there isn't a "join" method and you'll have to manually re-assemble each list of integers into a dot-separated string.

 

tfoiltfoil

Yeah, You are right, Tomcollins.

 

It doesn't work for '10', '11", etc.

 

I will try your sugestion. Thank you very much.

tfoiltfoil

Thank you all. Here is the solution.

 

Some comments and variable names are in Brazilian Portuguese, sorry for that.

 

global class PacoteWrapper implements Comparable {

public Pacote__c pac;

public PacoteWrapper(Pacote__c pc) {
pac = pc;
}

global Integer compareTo(Object compareTo) {

PacoteWrapper compareToPac = (PacoteWrapper)compareTo;

Integer returnValue = 0;

// Ordenando arrays de inteiros
// Lista A
Integer[] ListA = new Integer[]{};
if(pac.Posicao_EDT__c != null)
{
if(pac.Posicao_EDT__c.contains('.')){
for(string a : pac.Posicao_EDT__c.split('\\.')){
ListA.add(Integer.Valueof(a));
}
}
else
{
ListA.add(Integer.Valueof(pac.Posicao_EDT__c));
}
}

// Lista B
Integer[] ListB = new Integer[]{};
if(compareToPac.pac.Posicao_EDT__c != null)
{
if(compareToPac.pac.Posicao_EDT__c.contains('.')){
for(string b : compareToPac.pac.Posicao_EDT__c.split('\\.')){
ListB.add(Integer.Valueof(b));
}
}
else
{
ListB.add(Integer.Valueof(compareToPac.pac.Posicao_EDT__c));
}
}

//Se o tamanho dos Arrays for diferente, faz os doi arrays terem o mesmo tamanho, completando com zero
if(ListB.size() != ListA.size()){

Integer diferenca = 0;

if(ListA.size() > ListB.size()){
diferenca = ListA.size() - ListB.size();
for(Integer i =0; i < diferenca; i++){
ListB.add(0);
}
}else{
diferenca = ListB.size() - ListA.size();
for(Integer i =0; i < diferenca; i++){
ListA.add(0);
}
}
}

Integer index = 0;
while (index < ListA.size()) {

if (ListA[index] > ListB[index]) {
return 1;
} else if (ListA[index] < ListB[index]) {
return -1;
}

index++;
}

return returnValue;
}
}

This was selected as the best answer