views:

268

answers:

8

So I have this "list" of ints. It could be a Vector, int[], List<Integer>, whatever.

My goal though is to sort the ints and end up with a String[]. How the int array starts out as is up in the air.

ex: Start with:{5,1,2,11,3} End with: String[] = {"1","2","3","5","11"}

Is there anyway to do this without a for loop? I have a for loop now for collecting the ints. I would rather skip doing another for loop.

A: 

You can use Collections.sort() and then iterate over the list and collectString.valueOf() each element.

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#sort%28java.util.List%29

For a Vector, you would first get a List with Collections.list(Enumeration e).

For an array, you would use Arrays.sort() instead of Collections.sort().

http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort%28int%5b%5d%29

gpeche
`Vector` is-a `List`.
Tom Hawtin - tackline
Oh, yes it is. I don't use `Vector` s that much as they are obsolete, so i didn't know they became `List` s. I remembered when you would iterate them with `Vector.elements()` (long ago).
gpeche
Vector, Hashtable, StringBuffer: These classes are all somewhat obsolete but folks keep using them. New folks, too. I wonder where they learn that...
seanizer
@seanizer:I have never heard StringBuffer to be obsolete.Can you refer to any article?
Emil
`StringBuilder` obsoletes `StringBuffer` for most cases.http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html
gpeche
@gpeche exactlty
seanizer
+5  A: 

Can I use a while loop instead?

@Test
public void test() {
    int[] nums = {5,1,2,11,3};

    Arrays.sort(nums);

    String[] stringNums = new String[nums.length];
    int i = 0;
    while (i < nums.length) {
        stringNums[i] = String.valueOf(nums[i++]);
    }

    Assert.assertArrayEquals(new String[]{"1","2","3","5","11"}, stringNums);
}

Using JUnit assertions.

Sorry, I'm being flippant. But saying you can't use a for loop is daft - you've got to iterate over the list somehow. If you're going to call a library method to sort it for you (cf Collections.sort()) - that will be looping somehow over the elements.

Noel M
where's the sorting?
seanizer
Sorry, got ahead of myself.
Noel M
+1  A: 

How about something like this:

List<String> stringList = new ArrayList<String>();
List<Integer> list = new ArrayList<Integer>(Arrays.asList(5,1,2,11,3));
Collections.sort(list);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
  stringList.add(iterator.next().toString());
}
System.out.println(stringList);
Adam
+2  A: 

If you use a TreeSet, I have a (longish) one-liner for you (assuming items is the TreeSet):

final String[] arr =
    items.toString() // string representation
        .replaceAll("\\D+", " ") // replace all non digits with spaces
        .trim() // trim ends
        .split(" "); // split by spaces

Test code:

Set<Integer> items = new TreeSet<Integer>(Arrays.asList(5, 1, 2, 11, 3));

// insert above code here

System.out.println(Arrays.toString(arr));

Output:

[1, 2, 3, 5, 11]

EDIT:

OK, here is a different version that works with the int array directly. But unfortunately it's not a one-liner. However, it does keep duplicates and it's probably faster

EDIT again:

Bug fixed and negative numbers supported, as requested:

EDIT once more: only one regex pass and no trim

    final int[] in = { 5, 1, 2, 11, 3, 2, -5 }; // with duplicate
    Arrays.sort(in);
    final String[] out =
        Arrays.toString(in)
            .replaceAll("(?:\\[?)([-\\d]+)(?:\\]?)", "$1") // just remove [ and ]
            .split("\\s*,\\s*"); // split by comma

    System.out.println(Arrays.toString(out));

Output:

[-5, 1, 2, 2, 3, 5, 11]

Or completely without regex (apart from split()), but with one more step added:

final int[] in = { 5, 1, 2, 11, 3, 2, -5 }; // with duplicate
Arrays.sort(in);
final String stringRep = Arrays.toString(in);
final String[] out =
    stringRep.substring(1, stringRep.length() - 1).split("\\s*,\\s*");

System.out.println(Arrays.toString(out));

Output:

[-5, 1, 2, 2, 3, 5, 11]

Update: stripped whitespace from my last two solutions, hope you're happy now :-)

seanizer
This won't work correctly for any array or list with more than 1 of the same element.
ColinD
+1 @ColinD. `TreeSet` will sort the numbers for you but it will also remove the duplicates, which is not what is intended.
missingfaktor
I know, but nobody said anything about keeping dupes
seanizer
Lists and arrays (mentioned in the question) keep duplicates, so I feel like it's kind of implicit.
ColinD
Okay, see my update.
seanizer
+1 for the correct code (and the cool regex stuff) :-)
missingfaktor
little changes needed for correctly handling negative numbers, and there is an undefined `arr` being used instead of `in`...
Carlos Heuberger
Negative numbers also? OK, see my update again ...
seanizer
@seanizer: No need to handle the number's type in regex just remove the opening and closing braces and split with ", ".
Emil
@emil true, but I don't think that's any simpler
seanizer
Check my answer.I told so because you wouldn't have to handle negative values.
Emil
Also leave a space after ',' other wise all numbers will have an extra space.
Emil
@emil, ok here we go again. whitespace is now stripped
seanizer
+1  A: 

I would rather skip doing another for loop.

That's silly. It's a silly desire and a silly basis for undertaking a code exercise. If you can better express the qualities that you want your code to have, then we've got something to talk about - that it should be easy to read, say, or performant, or testable, or robust. But "I'd rather skip it" just doesn't give us anything useful to work with.

Carl Manaster
Because I already loop to get the list. Thanks for playing though.
+3  A: 

Simple solution using Guava:

public List<String> toSortedStrings(List<Integer> ints) {
  Collections.sort(ints);
  return Lists.newArrayList(Iterables.transform(ints, 
      Functions.toStringFunction()));
}

Obviously, this solution (like any other) is going to use loops internally, but it gets it out of the code you have to read. You could also avoid changing the order in ints by passing the result of Ordering.natural().sortedCopy(ints) to transform instead of using Collections.sort first. Also, the Lists.newArrayList part is not necessary if you don't need to be able to add new elements to the resulting list.

The shortened version of that method body, with static imports:

return transform(Ordering.natural().sortedCopy(ints), toStringFunction());
ColinD
+1  A: 

Using Functional Java,

import fj.data.List;
import static fj.data.List.*;
import static fj.pre.Show.*;
.
.
.
final List<Integer> xs = list(5,1,2,11,3);
final List<String> ys = xs.sort(Ord.intOrd).map(
  new F<Integer, String>() {
    @Override public String f(final Integer i) {
       return String.valueOf(i);
    }
  }
);
listShow(stringShow).println(ys);
missingfaktor
that's cool!! (if I had any remaining votes I'd upvote it) :-)
seanizer
@seanizer: Well, you can always come back and upvote. ;-)
missingfaktor
Here's the Upvote now, as promised :-)
seanizer
@seanzier: Thanks, much appreciated! :)
missingfaktor
A: 
int[] nums = {5,1,2,11,3}; //List or Vector
Arrays.sort(nums); //Collections.sort() for List,Vector
String a=Arrays.toString(nums); //toString the List or Vector
String ar[]=a.substring(1,a.length()-1).split(", ");
System.out.println(Arrays.toString(ar));

UPDATE:

A shorter version:

int[] nums = {-5,1,2,11,3};
Arrays.sort(nums);
String[] a=Arrays.toString(nums).split("[\\[\\]]")[1].split(", "); 
System.out.println(Arrays.toString(a));  
Emil
I think this could be the answer. I didn't want to interate through the list a second time because I'm already iterating to get the int list. Thank you.
if your concerned about speed then its better to use the normal for loop once more because in Arrays.toString() they are using a for loop.Check the source(http://www.docjar.com/html/api/java/util/Arrays.java.html) But if you just want your code to look small then ok,you can use the above code or another option is just write small function to sent an int[] as input and return String[] array as output.
Emil