Related
I'm trying to generate the 2-letter State Code, I'm storing the countries in a list of strings. Now, the criteria are:-
The First letter of the state code must be the first letter of the state. For ex- If the state is Alabama, the first letter must be A.
The second letter of the state code can be any random letter from the word.
Now if we give 5 states then it should return 5 unique values.
PS: I'm attaching the code below, here I'm trying to convert the list into a set but the set is removing the duplicates, I want all the distinct values without repetition.
Input:[Alabama, Alaska, Alain, Bombay, Borland]
Expected Output:[AL, AK, AA, BO, BR]
public class RadnomStateGenerator
{
public static void main(String[] args)
{
List<String> stateList = new ArrayList<String>();
stateList.add("ALABAMA");
stateList.add("ALASKA");
stateList.add("ALAIN");
stateList.add("BOMBAY");
stateList.add("BORLAND");
System.out.println(stateList);
HashSet<String> hset = new HashSet<String>();
for(String string:stateList)
{
char fWord = string.charAt(0);
int value = (int) (Math.random() * string.length() - 1);
char sWord = string.charAt(value);
String newstr = ((Character.toString(fWord) + Character.toString(sWord)).toUpperCase());
hset.add(newstr);
}
System.out.println(hset);
}
}
When adding an entry to a set, the method add returns true only if the set has changed that is the entry has been added. This can help detect duplicates and therefore attempt to create another code:
public static void main(String[] args) {
List<String> stateList = Arrays.asList("ALABAMA", "ALASKA", "ALAIN", "BOMBAY", "BORLAND");
System.out.println(stateList);
Set<String> hset = new LinkedHashSet<String>();
Random r = new Random();
for (String string : stateList) {
int len = string.length() - 1;
String first = string.substring(0, 1);
while (true) {
String code = first + string.charAt(1 + r.nextInt(len));
if (hset.add(code)) { // set changed
break;
}
}
}
System.out.println(hset);
}
Example:
[ALABAMA, ALASKA, ALAIN, BOMBAY, BORLAND]
[AA, AK, AI, BY, BL]
or
[ALABAMA, ALASKA, ALAIN, BOMBAY, BORLAND]
[AM, AL, AI, BB, BR]
It's worth to mention that chances to get AA for ALABAMA is ~50% because of three A's after the initial one.
Given a string with repeating pattern here:
String s = NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500
Essentially I want way where when NameJJ and firstname are beside each other like at top it stores value beside them which is arraylist1 = [120,200].
Essentially I want way where all field with NameBB and secondname are beside each other to store the value beside them which is arraylist2 = [100,300].
Essentially I want way where all field with NameJJ and thirdname are beside each other to store the value beside them which is arraylist3 = [150,500].
I was trying to do this to say if string contains NameJJ and contains firstname should filter out value beside it but I'm confused on how I would do that, this is the code :
if (s.contains(NameJJ) && s.contains(firstname))
Pattern reg = Pattern.compile(",");
ArrayList<String> SANR = reg.splitAsStream(s)
.filter(role -> role.contains(""))
.map(String::trim)
.collect(Collectors.toCollection(ArrayList::new));
Your String s holds the complete data so if (s.contains(NameJJ) && s.contains(firstname)) will always be true.
You have to split the blocks first, then look at the values.
Your data block contains 3 data each so that's the number you have to divide by in loop condition and multiply with in array access
String s = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";
String[] split = s.split(",");
List<Integer> first = new ArrayList<>();
List<Integer> second = new ArrayList<>();
List<Integer> third = new ArrayList<>();
for (int i = 0; i < split.length / 3; i++) {
// first data block is Name..
// second block is firstname/secondname/thirdname
// third block hold the number you want
if (split[3 * i].trim().equals("NameJJ") && split[3 * i + 1].trim().equals("ABC/firstname")) {
first.add(Integer.parseInt(split[3 * i + 2].trim()));
} else if (split[3 * i].trim().equals("NameBB") && split[3 * i + 1].trim().equals("ABC/secondname")) {
second.add(Integer.parseInt(split[3 * i + 2].trim()));
} else if (split[3 * i].trim().equals("NameCC") && split[3 * i + 1].trim().equals("ABC/thirdname")) {
third.add(Integer.parseInt(split[3 * i + 2].trim()));
}
}
System.out.println(first);
System.out.println(second);
System.out.println(third);
Output is
[120, 200]
[100, 300]
[150, 500]
As I've answered in a previous question of yours, whenever you're having a certain pattern repeating itself, you should use a regex to extract the sub-bits of your pattern.
Streams are not designed to keep track of a "first" or "last" element. They're mainly stateless operations, with a few exceptions for distinct, sorted and similar. Stateless operations start their execution even before the previous one has finished its computation. This is why they have no recollection of a first or last result and also why we cannot use them for this kind of tasks.
What you could do is to employ 3 regex to match your pattern for nameJJ, nameBB and nameCC, and use capturing groups to identity and extract every desired sub-bit.
The following 3 regex can be used to match your patterns:
(\w+)JJ,(\w+)\/(\w+),(\d+)
(\w+)BB,(\w+)\/(\w+),(\d+)
(\w+)CC,(\w+)\/(\w+),(\d+)
Here is a snippet of the code implementation:
public class Main {
public static void main(String[] args) {
String s = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";
List<Integer> listNameJJ = getList("(\\w+)JJ,(\\w+)\\/(\\w+),(\\d+)", s);
List<Integer> listNameBB = getList("(\\w+)BB,(\\w+)\\/(\\w+),(\\d+)", s);
List<Integer> listNameCC = getList("(\\w+)CC,(\\w+)\\/(\\w+),(\\d+)", s);
System.out.println(listNameJJ);
System.out.println(listNameBB);
System.out.println(listNameCC);
}
public static List<Integer> getList(String regex, String str) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
List<Integer> list = new ArrayList<>();
while (matcher.find()) {
list.add(Integer.valueOf(matcher.group(4)));
}
return list;
}
}
Here is also a link to test the code above:
https://ideone.com/TES5UY
Here is another example,
public class Application {
public static void main(String[] args) {
String yourString = "NameJJ,ABC/firstname,120, NameBB,ABC/secondname,100,NameCC,ABC/thirdname,150,NameJJ,ABC/firstname,200,NameBB,ABC/secondname,300,NameCC,ABC/thirdname,500";
String myString = "NameKK,ZXY/kname,510, NameQQ,HLM/kname,210, NameKK,ZXY/kname,210,";
// Test 1
System.out.println(getValues("NameJJ", "firstname", yourString));
// Test 2
System.out.println(getValues("NameKK", "kname", myString));
}
private static List<Integer> getValues(String str1, String str2, String inputString) {
// Note* List is an ordered sequence of elements.
List<Integer> value = new ArrayList<Integer>();
// Extract Values
Matcher m = Pattern.compile("-?\\d+(,\\d+)*?\\.?\\d+?")
.matcher(inputString);
while (m.find()) {
value.add(Integer.parseInt(m.group().trim()));
}
// Extract Keys
List<String> key = List.of(inputString.split("\\d+"));
List<Integer> result = new ArrayList<Integer>();
// Filtering
for (int i = 0; i < value.size(); i++) {
if (key.get(i).trim().contains(str1)
&& key.get(i).trim().contains(str2)) {
result.add(value.get(i));
}
}
return result;
}
}
Console O/P:
[120, 200]
[510, 210]
I have to remove a duplicate value from a String.
But first I have to filter the given value that needs to be deleted. And if it's a duplicate, return a new String with first duplicated value removed. And I want to do this using lambdas.
Example.
Input (filter the value: "A")
String input = "A, A, C";
Expected output
"A, C"
But if I have this.
Input (filter a value different to "A")
String input = "A, A, C";
Expected output
"A, A, C"
I.e. if the given filter-value is a duplicate, like "A", which is encountered in the string multiple times, then its first occurrence has to be removed. Otherwise, the same string should be returned.
The white spaces and commas has to be considered in the output too.
I have been tried this code:
public class Main {
public static void main(String[] args) {
String mercado = "A, B, A";
mercado = mercado.replaceAll("\\b(A)\\b(?=.*\\b\\1\\b)", "");
System.out.println( mercado );
}
}
But the output is: , B, A
And I have to remove that white space and that comma in front.
If I understood your goal correctly, you need a method that expects two string arguments.
And depending on the number of occurrences of the second string in the first string the method will return either the first string intact (if the target value is unique or not present in the first string), or will generate a new string by removing the first occurrence of the target value (the second string).
This problem can be addressed in the following steps:
Create a list by splitting the given string.
Count the number of occurrences of the target value.
If the count is <= 1 (i.e. value is unique, or not present at all) return the same string.
Otherwise remove the target value from the list.
Combine list elements into a string.
It might be implemented like this:
public static String removeFirstIfDuplicate(String source, String target) {
List<String> sourceList = new ArrayList<>(Arrays.asList(source.split("[\\p{Punct}\\p{Space}]+")));
long targetCount = sourceList.stream()
.filter(str -> str.equals(target))
.count();
if (targetCount <= 1) {
return source;
}
sourceList.remove(target);
return sourceList.stream().collect(Collectors.joining(", "));
}
main()
public static void main(String[] args) {
System.out.println(removeFirstIfDuplicate("A, A, C", "A"));
System.out.println(removeFirstIfDuplicate("A, A, C", "C"));
}
Output
A, C
A, A, C
I have some strings defined in my Java application, like so:
m3 = "T, V, E";
m2 = "T, W, E";
as an example.
Now I need to check, which parts of the strings match. So in this case, I would want a string m4, containing T, E, as a result.
In that case for example:
m1 = "A, S";
m3 = "T, V, E";
i would want an empty (but declared) string.
Or is there a better way, to do it with another method then with strings? I'm actually declaring those strings by hand. Would an array be better? If yes, how could I do it with arrays?
In Java 8 you can proceed as below :
String s1 = "T,V,E";
String s2 = "T,W,E";
List<String> l1 = Arrays.asList(s1.split(","));
List<String> l2 = Arrays.asList(s2.split(","));
List<String> result = l1.stream().filter(l2::contains).collect(Collectors.toList());
System.out.println(String.join(",", result));
The result is "T,E" as expected.
You can achieve this in many ways. One of the ways is using Set.
First, split m1 the characters by (comma) and add it to HashSet. Then split the m2 characters and add it to ArrayList. Now by the for loop try to add the ArrayList characters to HashSet. You will get false from the add method (Set.add()) if it is not added (because the character is already there). If you get false print the character or add it to another ArrayList.
String m3 = "T, V, E";
String m2 = "T, W, E";
Set<String> set = new HashSet<>(Arrays.asList(m3.split(",")));
List<String> list = Arrays.asList(m2.split(","));
for (String s : list) {
if (!set.add(s)) {
System.out.println(s);
}
}
Result will be T and E
The appropriate data structure is Set.
Set<String> m3 = new TreeSet<>();
Collections.addAll(m3, "T", "V", "E");
Collections.addAll(m3, "T, V, E".split(",\\s*")); // Alternatively.
Set<String> m2 = new HashSet<>();
Collections.addAll(m2, "T", "W", "E");
Set<String> m5 = new TreeSet<>(m2);
m5.retainAll(m3);
Java 9:
Set<String> m3 = Set.of("T", "V", "E");
Set<String> m2 = Set.of("T", "W", "E");
you can use the split() function as the following
String a="A, B, C, D";
String b="B, C, D";
String[] a_chars =a.split(", "); //returns array with A B C D
String[] b_chars =b.split(", "); //returns array with B C D
this whay you have 2 arrays of strings now you can compare them using 2 (for) loops
String result="";
for(int c=0;c<a_chars.length;c++)
{
for(int d=0;d<b_chars.length;d++)
{
if(a_chars[c].equals(b_chars[d]))
{
result+=a_chars[c]+", ";
}
}
}
now you have the result string like this result="B, C, D, "
check of the length of result is greater than zero
if so erase the lase 2 characters which are ,
if(result.length()>0)result=result.substring(0,result.length()-2);
if the length of the result string is zero that means there is no matching letters so no need to modify it
If all your String follows this pattern : ..., ..., .... , you could split them and filter only each String that is contained in the two arrays.
You can then collect them into a List and join them with , :
List<String> commonStrings = Arrays.stream(m2.split(",\\s"))
.flatMap(s-> Arrays.stream(m3.split(",\\s"))
.filter(s2.equals(s)))
.collect(Collectors.toList());
String joinedString = String.join(",", commonStrings);
Note that this code doesn't return the exact number of equals occurrences in the two Strings.
So if one String contains two A and the other one A, you will get two A in the result.
If it doesn' matter and you want to get only distinct String, you can invoke distinct() before collect().
Otherwise, to return the exact number of equals occurrences, during the processing, as soon as a String part is consumed (A for example) as the two parts are equal in the two Strings, you could create new Strings from the actual Strings but by removing this String part .
String s1 = "T,V,E";
String s2 = "T,W,E";
List<String> l1 = Arrays.asList(s1.split(","));
List<String> l2 = Arrays.asList(s2.split(","));
List<String> result = l1.stream().filter(l2::contains).collect(Collectors.toList());
System.out.println(String.join(",", result));
result = T&E
This is good answer I will tell you too this
I have a String that's formatted like this:
"key1=value1;key2=value2;key3=value3"
for any number of key/value pairs.
I need to check that a certain key exists (let's say it's called "specialkey"). If it does, I want the value associated with it. If there are multiple "specialkey"s set, I only want the first one.
Right now, I'm looking for the index of "specialkey". I take a substring starting at that index, then look for the index of the first = character. Then I look for the index of the first ; character. The substring between those two indices gives me the value associated with "specialkey".
This is not an elegant solution, and it's really bothering me. What's an elegant way of finding the value that corresponds with "specialkey"?
I would parse the String into a map and then just check for the key:
String rawValues = "key1=value1;key2=value2;key3=value3";
Map<String,String> map = new HashMap<String,String>();
String[] entries = rawValues.split(";");
for (String entry : entries) {
String[] keyValue = entry.split("=");
map.put(keyValue[0],keyValue[1]);
}
if (map.containsKey("myKey")) {
return map.get("myKey");
}
Use String.split:
String[] kvPairs = "key1=value1;key2=value2;key3=value3".split(";");
This will give you an array kvPairs that contains these elements:
key1=value1
key2=value2
key3=value3
Iterate over these and split them, too:
for(String kvPair: kvPairs) {
String[] kv = kvPair.split("=");
String key = kv[0];
String value = kv[1];
// Now do with key whatever you want with key and value...
if(key.equals("specialkey")) {
// Do something with value if the key is "specialvalue"...
}
}
If it's just the one key you're after, you could use regex \bspecialkey=([^;]+)(;|$) and extract capturing group 1:
Pattern p = Pattern.compile("\\bspecialkey=([^;]+)(;|$)");
Matcher m = p.matcher("key1=value1;key2=value2;key3=value3");
if (m.find()) {
System.out.println(m.group(1));
}
If you're doing something with the other keys, then split on ; and then = within a loop - no need for regex.
Just in case anyone is interested in a pure Regex-based approach, the following snippet works.
Pattern pattern = Pattern.compile("([\\w]+)?=([\\w]+)?;?");
Matcher matcher = pattern.matcher("key1=value1;key2=value2;key3=value3");
while (matcher.find()) {
System.out.println("Key - " + matcher.group(1) + " Value - " + matcher.group(2);
}
Output will be
Key - key1 Value - value1
Key - key2 Value - value2
Key - key3 Value - value3
However, as others explained before, String.split() is recommended any day for this sort of task. You shouldn't complicate your life trying to use Regex when there's an alternative to use.
There are many ways to do this. Perhaps the simplest is to use the Streams API (available as of Java 8 and later) to process the match results:
List<String> OriginalList = Arrays.asList("A=1,B=2,C=3",
"A=11,B=12,C=13,D=15", "A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33", "A=77,B=27,C=37");
this streams the strings
matches on the pattern and extracts the integer
the collects to a list
Pattern p = Pattern.compile("A=(\\d+)");
List<Integer> result = OriginalList.stream().
flatMap(str->p.matcher(str).results())
.map(mr->Integer.valueOf(mr.group(1)))
.collect(Collectors.toList());
System.out.println(result);
Prints:
[1, 11, 5, 19, 77]
Try : (?:(?:A=)([^,]*))
Demo : https://regex101.com/r/rziGDz/1
Else you find a code using regex and your list to get answer :
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
public class Main
{
public static void main(String[] args)
{
List<Integer> results = new ArrayList();
Pattern pattern = Pattern.compile("(?:(?:A=)([^,]*))", Pattern.CASE_INSENSITIVE);
List<String> OriginalList = Arrays.asList(
"A=1,B=2,C=3",
"A=11,B=12,C=13,D=15",
"A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33",
"A=77,B=27,C=37");
for (int i = 0; i < OriginalList.size(); i++)
{
Matcher matcher = pattern.matcher(OriginalList.get(i));
boolean matchFound = matcher.find();
if(matchFound)
{
System.out.println( matcher.group(1) );
results.add( Integer.parseInt(matcher.group(1)) );
}
}
}
}
This may be implemented using Stream API by simple splitting of each string in the input list by comma and Stream::flatMap
// assuming A is not always at the beginning
List<String> list = Arrays.asList(
"A=1,B=2,C=3",
"A=11,B=12,C=13,D=15",
"A=5,B=4,C=9,D=10,E=13",
"B=20,C=91,D=40,E=33",
"B=27, A=19, C=37, A=77");
List<Integer> aNums = list.stream() // Stream<String>
.flatMap(
s -> Arrays.stream(s.split("\\s*,\\s*")) // Stream<String> pairs of letter=digits
.filter(pair -> pair.startsWith("A="))
.map(pair -> Integer.valueOf(pair.substring(2)))
)
.collect(Collectors.toList());
System.out.println(aNums);
Output:
[1, 11, 5, 19, 77]
Update
A pattern to split an input string and keep only the digits related to A may be applied as follows:
Pattern splitByA = Pattern.compile("A\\s*=\\s*|\\s*,\\s*|[^A]\\s*=\\s*\\d+");
List<Integer> aNums2 = list.stream()
.flatMap(splitByA::splitAsStream) // Stream<String>
.filter(Predicate.not(String::isEmpty)) // need to remove empty strings
.map(Integer::valueOf)
.collect(Collectors.toList());
System.out.println(aNums2);
Output is the same
[1, 11, 5, 19, 77]
Using basic filter: Split using [A-Z=,]+ regex. Pick the 2nd element.
public List filter() {
List<String> originalList = Arrays.asList("A=1,B=2,C=3", "A=11,B=12,C=13,D=15", "A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33", "A=77,B=27,C=37");
List<Integer> parsedData = new ArrayList();
for(String str: originalList) {
Integer data = Integer.parseInt(str.split("[A-Z=,]+")[1]);
parsedData.add(data);
}
return parsedData;
}
Try this:
List<Integer> results = new ArrayList();
Pattern p = Pattern.compile("(?:(?:A=)([^,]*))");
Matcher m = null;
for (String tmp : OriginalList) {
m = p.matcher(tmp);
if (m.find()) {
int r = Integer.parseInt(m.group(0).replace("A=", ""));
results.add(r);
}
}