How to modify the value of a Hashmap, which has key&value as Strings,and the 'value' is a single string consisting of comma separated values - string

I am trying to modify a Hashmap .
The 'value' is a single string consisting of comma separated values.
(for e.g.: "aid=abc,bid=def,cid=gh2")
I need to replace particular values from them with a corresponding value from the DB.
(for e.g. changing the bid to 123, which would result in the above 'value' string as: "aid=abc,bid=123,cid=gh2")
And then set the modified 'value' to the corresponding key, so that the hashmap consists of modified values.
I tried to iterate through the keys , and with map(key) which will give the value, I tried to convert that to a list of comma separated values and then iterate through that list, and in each of the string, if I find 'bid'(example string above), then I do the necessary manipulation and then set it back to the Hashmap(which I Wasnt able to do since Strings arent mutable)
for (String name :outputMap.keySet())
List urlList = Arrays.asList(outputMap.get(name).split(",")); for(int i=0;i
expected result:"aid=abc,bid=123,cid=gh2" (post the manipulation)
actual result: unable to do.
I have used Stringbuffer for issues where string had to be modified, but was a little apprehensive to use that here, since this has already multiple conversions going.
The code needs to Java 7 compliant, since this is being deployed in a Client machine still using some legacy environment.(They are scheduled to migrate to java 8 , but thats scheduled for much later)
Any assistance here would be appreciated.

static Map<String, String> replace(Map<String, String> map, String toReplace, String replacement) {
return map.entrySet().stream()
.collect(Collectors.toMap(Entry::getKey,
e -> transformValue(e.getValue(), toReplace, replacement)));
}
static String transformValue(String value, String toReplace, String replacement) {
return Arrays.stream(value.split(","))
.map(pair -> pair.split("="))
.map(sPair -> sPair[0] + "=" + (toReplace.equals(sPair[0]) ? replacement : sPair[1]))
.collect(Collectors.joining(","));
}
this will iterate through all entries of map and create a new map with changed values. Example:
var map = Map.of("key1", "aid=abc,bid=def,cid=gh2");
System.out.println(replace(map, "bid", "123").get("key1"));
will print aid=abc,bid=123,cid=gh2

Related

How to return specific option type by splitting a string using scala?

I have a following string and I want to split it using scala
"myInfo": "name-name;model-model;number-10"
I want to split value of myInfo string such that I can access myName and its value seperately. e.g. myName:name, model:R210 etc
I am using following code to split string.
val data = (mainString \ "myInfo").as[String].split("\\;").map(_.split("\\-").toList)
.collect { case key :: value :: _ => key -> value }.toMap
It gives me desired result.
I am using
data.get("name"),data.get("model"),data.get("number")
to access list.
It gives me results in string type. While I want to get result of data.get("number") in integer format.
How do I get result of 'number' in integer format?
data.get("number").map(_.toInt)
will return an Option[Int]

How to split string using scala?

I have a following string and I want to split it using scala
"myInfo": "myName-name;model-R210;"
I want to split value of myInfo string such that I can access myName and its value seperately.
e.g. myName:name, model:R210 etc
I am using following code to split string -
(mainString \ "myInfo").as[String].split("\\;").toList.map(_.split("\\-"))
where mainString is Json and contains 'myInfo' key value pair.
How do I split string to seperate it by '-' and access it?
You can obtain a Map[String,String] like so:
val data: Map[String,String] = (mainString \ "myInfo").as[String]
.split("\\;").map(_.split("\\-").toList)
.collect {
case key :: value :: _ => key -> value
}.toMap
Then access your values:
val name = data.getOrElse("myName", "DefaultNameIfMissing")
First of all, shame on whoever encoded a complex data structure into a string in a JSON document; you shouldn't have to parse it at all. If it's under your control, I'd change that to something like
"myInfo": {
"myName": "name",
"model": "R210"
}
But if you can't change the input, then just do this to get the Map you want:
val myInfo = ((mainString \ "myInfo").as[String] split ';' map (_ split '-') collect { case Array(k,v) => k->v } ).toMap
No need to create Lists out of the intermediate results -- that would just slow things down. And just split on a Char, not a String (which would get compiled as a regular expression).
Note that the collect causes any component with no hyphen or more than one hyphen to be ignored; you might want to do something else there.

How to detect a number in my Linked List of Strings, and get the value

I need to sort my Linked List, the problem is that each of my Linked List elements are Strings with sentences. So the question is... how to detect each number in my Linked List and get the value?.
I tried to split my linked list so I can pass trough each element.
private LinkedList<String> list = new LinkedList<String>();
list.add("Number One: 1")
list.add("Number Three: 3")
list.add("Number two:2")
for(Iterator<String> iterator =list.iterator(); iterator.hasNext(); )
{
String string = iterator.next();
for (String word : string.split(" ")){
}
I also tried with "if((word.contains("1") || (word.contains("2")...." inside the for loop, and then pass the value "word" to Double... but I think is not very smart
So my goal is this Output (Number One: 1 , Number Two: 2, Number Three: 3), therefore I need the value of each number first.
why not use tryParse on the string,
for (String word : string.split(" ")){
int outvalue
if(int.TryParse(word, outvalue)){
//DoSomething with result
}
}

Best way to compare multiple string in java

Suppose I have a string "That question is on the minds of every one.".
I want to compare each word in string with a set of word I.e. (to , is ,on , of) and if those word occurs I want to append some string on the existing string.
Eg.
to = append "Hi";
Is = append "Hello";
And so on.
To be more specific I have used StringTokenizer to get the each word and compared thru if else statement. However we can use Switch also but it is available in Jdk 1.
7.
I don't know if this is what you mean, but:
You could use String.split() to separate the words from your string like
String[] words = myString.split(" ");
and then, for each word, compare it with the given set
for(String s : words)
{
switch(s)
{
case("to"):
[...]
}
}
Or you could just use the String.contains() method without even splitting your string, but I don't know if that's what you wanted.
Use a HashMap<String,String> variable to store your set of words and the replacement words you want. Then split your string with split(), loop through the resulting String[] and for each String in the String[], check whether the HashMap containsKey() that String. Build your output/resulting String in the loop - if the word is contained in the HashMap, replace it with the value of the corresponding key in the HashMap, otherwise use the String you are currently on from the String[].

How to find all cyclic shifted strings in a given input?

This is a coding exercise. Suppose I have to decide if one string is created by a cyclic shift of another. For example: cab is a cyclic shift of abc but cba is not.
Given two strings s1 and s2 we can do that as follows:
if (s1.length != s2.length)
return false
for(int i = 0; i < s1.length(); i++)
if ((s1.substring(i) + s1.substring(0, i)).equals(s2))
return true
return false
Now what if I have an array of strings and want to find all strings that are cyclic shift of one another? For example: ["abc", "xyz", "yzx", "cab", "xxx"] -> ["abc", "cab"], ["xyz", "yzx"], ["xxx"]
It looks like I have to check all pairs of the strings. Is there a "better" (more efficient) way to do that?
As a start, you can know if a string s1 is a rotation of a string s2 with a single call to contains(), like this:
public boolean isRotation(String s1, String s2){
String s2twice = s2+s2;
return s2twice.contains(s1);
}
Namely, if s1 is "rotation" and s2 is "otationr", the concat gives you "otationrotationr", which contains s1 indeed.
Now, even if we assume this is linear, or close to it (which is not impossible using Rabin-Karp, for instance), you are still left with O(n^2) pair comparisons, which may be too much.
What you could do is build an hashtable where the sorted word is the key, and the posting list contains all the words from your list that, if sorted, give the key (ie. key("bca") and key("cab") both should return "abc"):
private Map<String, List<String>> index;
/* ... */
public void buildIndex(String[] words){
for(String word : words){
String sortedWord = sortWord(word);
if(!index.containsKey(sortedWord)){
index.put(sortedWord, new ArrayList<String>());
}
index.get(sortedWord).add(word);
}
}
CAVEAT: The hashtable will contain, for each key, all the words that have exactly the same letters occurring the same amount of times (not just the rotations, ie. "abba" and "baba" will have the same key but isRotation("abba", "baba") will return false).
But once you have built this index, you can significantly reduce the number of pairs you need to consider: if you want all the rotations for "bca" you just need to sort("bca"), look it up in the hashtable, and check (using the isRotation method above, if you want) if the words in the posting list are the result of a rotation or not.
If strings are short compared to the number of strings in the list, you can do significantly better by rotating all strings to some normal form (lexicographic minimum, for example). Then sort lexicographically and find runs of the same string. That's O(n log n), I think... neglecting string lengths. Something to try, maybe.
Concerning the way to find the pairs in the table, there could be many better way, but what I came up as a first thought is to sort the table and apply the check per adjacent pair.
This is much better and simpler that checking every string with every other string in the table
Consider building an automaton for each string against which you wish to test.
Each automaton should have one entry point for each possible character in the string, and transitions for each character, plus an extra transition from the end to the start.
You could improve performance even further if you amalgated the automata.
I think a combination of the answers by Patrick87 and savinos would make a fair amount of sense. Specifically, in a Java-esque pseudo-code:
List<String> inputs = ["abc", "xyz", "yzx", "cab", "xxx"];
Map<String,List<String>> uniques = new Map<String,List<String>>();
for(String value : inputs) {
String normalized = normalize(value);
if(!uniques.contains(normalized)) {
unqiues.put(normalized, new List<String>());
}
uniques.get(normalized).add(value);
}
// you now have a Map of normalized strings to every string in the input
// that is "equal to" that normalized version
Normalizing the string, as stated by Patrick87 might be best done by picking the rotation of the string that results in the lowest lexographic ordering.
It's worth noting, however, that the "best" algorithm probably relies heavily on the inputs... the number of strings, the length of those string, how many duplicates there are, etc.
You can rotate all the strings to a normalized form using Booth's algorithm (https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation) in O(s) time, where s is the length of the string.
You can then use the normalized form as a key in a HashMap (where the value is the set of rotations seen in the input). You can populate this HashMap in a single pass over the data. i.e., for each string
calculate the normalized form
check if the HashMap contains the normalized form as a key - if not insert the empty Set at this key
add the string to the Set in the HashMap
You then just need to output the values of the HashMap. This makes the total runtime of the algorithm O(n * s) - where n is the number of words and s is the average word length. The total space usage is also O(n * s).

Resources