Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split string into key-value pairs

Tags:

java

hashmap

I have a string like this:

pet:cat::car:honda::location:Japan::food:sushi

Now : indicates key-value pairs while :: separates the pairs. I want to add the key-value pairs to a map.

I can achieve this using:

Map<String, String> map = new HashMap<String, String>();
String test = "pet:cat::car:honda::location:Japan::food:sushi";
String[] test1 = test.split("::");

for (String s : test1) {
    String[] t = s.split(":");
    map.put(t[0], t[1]);
}

for (String s : map.keySet()) {
    System.out.println(s + " is " + map.get(s));
}

But is there an efficient way of doing this?


I feel the code is inefficient because I have used 2 String[] objects and called the split function twice. Also, I am using t[0] and t[1] which might throw an ArrayIndexOutOfBoundsException if there are no values.

like image 937
v1shnu Avatar asked Jul 01 '15 06:07

v1shnu


People also ask

How do you split a string into values?

Split is used to break a delimited string into substrings. You can use either a character array or a string array to specify zero or more delimiting characters or strings. If no delimiting characters are specified, the string is split at white-space characters.

How do you split a list in key-value pairs?

To split strings in list into key-value pairs: Use a generator expression to split the strings in the list into nested lists of key-value pairs. Pass the two-dimensional list to the dict() class.

How do you split a key-value pair in Python?

Method 1: Split dictionary keys and values using inbuilt functions. Here, we will use the inbuilt function of Python that is . keys() function in Python, and . values() function in Python to get the keys and values into separate lists.


2 Answers

Using Guava library it's a one-liner:

String test = "pet:cat::car:honda::location:Japan::food:sushi";
Map<String, String> map = Splitter.on( "::" ).withKeyValueSeparator( ':' ).split( test );
System.out.println(map);

The output:

{pet=cat, car=honda, location=Japan, food=sushi}

This also might work faster than JDK String.split as it does not create a regexp for "::".

Update it even handles correctly the corner case from the comments:

String test = "pet:cat::car:honda::location:Japan::food:sushi:::cool";
Map<String, String> map = Splitter.on( "::" ).withKeyValueSeparator( ':' ).split( test );
System.out.println(map);

The output is:

{pet=cat, car=honda, location=Japan, food=sushi, =cool}
like image 172
Tagir Valeev Avatar answered Oct 04 '22 22:10

Tagir Valeev


You could do a single call to split() and a single pass on the String using the following code. But it of course assumes the String is valid in the first place:

    Map<String, String> map = new HashMap<String, String>();
    String test = "pet:cat::car:honda::location:Japan::food:sushi";

    // split on ':' and on '::'
    String[] parts = test.split("::?");

    for (int i = 0; i < parts.length; i += 2) {
        map.put(parts[i], parts[i + 1]);
    }

    for (String s : map.keySet()) {
        System.out.println(s + " is " + map.get(s));
    }

The above is probably a little bit more efficient than your solution, but if you find your code clearer, then keep it, because there is almost zero chance such an optimization has a significant impact on performance, unless you do that millions of times. Anyway, if it's so important, then you should measure and compare.

EDIT:

for those who wonder what ::? means in the above code: String.split() takes a regular expression as argument. A separator is a substring that matches the regular expression. ::? is a regular expression which means: 1 colon, followed by 0 or 1 colon. It thus allows considering :: and : as separators.

like image 27
JB Nizet Avatar answered Oct 04 '22 21:10

JB Nizet