AD17
AD17

Reputation: 19

Trying to count the number of data types in a string

So at the input, a string contains different types of data. Basically, this is a string, int, and float. I check types through Float.parseFloat() and Integer.parseInt(). the Integer.parseInt() works correctly, yet Float.parseFloat() includes all the digits that are checked. How to avoid this?

The problem is that when checking for the float type, it also considers ints (output):

public class TypeCountString {
    public static void countTypeInString(String string){
        String[] value = string.split(" ");
        float ifFloat;
        int ifInt;
        String ifString;
        int counter = 0;
        // count Floats
        for (String i: value){
            try{
                ifFloat = Float.parseFloat(i);
                counter++;
                continue;
            } catch (NumberFormatException e){
            }
        }
        System.out.println("Float " + counter);

        //count ints
        counter = 0;
        for (String i: value){
            try{
                ifInt = Integer.parseInt(i);
                counter++;
                continue;
            } catch (NumberFormatException e){
            }

        }
        System.out.println("Int " + counter);

        //counts strings
        String stringOfStrings = string.replaceAll("[0-9.]","");
        stringOfStrings = stringOfStrings.replaceAll("  "," ");
        String[] value2 = stringOfStrings.split(" ");
        System.out.println("String " + value2.length);


    }

    public static void main(String[] args) {
        String string = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
        System.out.println(string);
        countTypeInString(string);
    }
}

Upvotes: 1

Views: 13348

Answers (3)

dani-vta
dani-vta

Reputation: 7130

Parsing first each substring to float will also parse integers as such, since integers are a subset of real numbers.

You should instead start parsing to the most restrictive type (in terms of possible values) up to the least restrictive. In your case, the possible values are: integers, real numbers, and strings. Therefore, you could try first to parse each substring to integer. If it fails, try to parse it as a real number. If that fails too, just treat it as a String.

Starting with integers is critical, as a decimal separator can't ever appear in an integer, leaving no doubts on what we're parsing, while with real numbers, a separator may or may not appear.

To handle each parsing, just use a try-catch, and nest each attempt in a catch block that handles NumberFormatException. Here is a possible implementation:

public class Main {
    public static void main(String[] args) {
        countTypesInString();
    }

    public static void countTypesInString() {
        String str = "Hello my 50 name 4.5 is James, I 20 years old and i have 5.7 coins";
        String[] vetStr = str.split("\\s+");

        List<Integer> listInt = new ArrayList<>();
        List<Float> listFloat = new ArrayList<>();
        List<String> listStr = new ArrayList<>();

        for (String s : vetStr) {
            try {
                // attempt int parsing
                listInt.add(Integer.parseInt(s));
            } catch (NumberFormatException exInt) {
                try {
                    // attempt float parsing
                    listFloat.add(Float.parseFloat(s));
                } catch (NumberFormatException exFloat) {
                    // just treat it as a String
                    listStr.add(s);
                }
            }
        }

        System.out.println("Number of ints: " + listInt.size() + " => " + listInt);
        System.out.println("Number of floats: " + listFloat.size() + " => " + listFloat);
        System.out.println("Number of strings: " + listStr.size() + " => " + listStr);
    }
}

Output:

Number of ints: 2 => [50, 20]
Number of floats: 2 => [4.5, 5.7]
Number of strings: 12 => [Hello, my, name, is, James,, I, years, old, and, i, have, coins]

As a side note, you might want to use double instead of float to represent real numbers, as the former offers a higher precision compared to the latter. In fact, Java treats decimal literals as a double by default.

Upvotes: 2

Kaan
Kaan

Reputation: 5794

Some tokens (like "50") are parseable both as integer and float. Your code gives both of them a chance, even though your intention is to only count each token as one type or the other (so count "50" as an integer, not as a float).

A simple fix could be to modify your float check to be:

  • make sure that i can pass Float.parseFloat(), and
  • confirm that i contains a decimal point

That code edit could look like this:

Float.parseFloat(i);
if (i.contains(".")) {
    counter++;
    continue;
}

Or, as a more involved alternative, instead of checking all input tokens for floats, then re-checking all input tokens for integers, I would take a different approach.

First, I would change the code to stop checking the entire input string repeatedly. This is helpful for 2nd part below, but also cleans up an unnecessary inefficiency of re-checking tokens even if you've already identified their data type. If you had a large number of tokens, it's wasteful to try parsing all of them as float, then try all of them as integer, then try a third time to count plain strings.

Second, since you would be checking (and counting) each token only one time, you could:

  • check for integer (before float) – if it passes Integer.parseInt(), increment that counter and move on to the next token
  • if it doesn't parse as integer, make an attempt to parse that token as float – just Float.parseFloat() without looking for decimal; if it worked then bump counter, move to next token
  • if it doesn't parse as integer or float, you know it's a String so simply bump the counter, then next token

Upvotes: 2

sean
sean

Reputation: 61

As Integer is a sub-type of Float, Float will count in Integers into your float count. If you solely just want the number of float that is not integer, just take float count minus integer count.

Upvotes: 2

Related Questions