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
Related
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
Given a list of strings of different length, we need find out string that would come in first in dictionary among strings generated by combination of given strings.
For Input:
cda,bcs,fgr,cd
output should be bcscdcdefgr
Is there any better way than generating all the combinations of strings and comparing them? Please help.
It appears that you just want ascending dictionary order. If so, then a plain collections sort should work here:
List<String> words = Arrays.asList(new String[] { "cda", "bcs", "fgr", "cd" });
Collections.sort(words);
String output = String.join("", words);
System.out.println(output);
This prints:
bcscdcdafgr
You can try this approach. Sorting directly would fail as b would before ba.
List<String> words = Arrays.asList(new String[] {"b","ba","c"});
Collections.sort(words,new Comparator<String>(){
#Override
public int compare(String s1, String s2) {
return (s1+s2).compareTo(s2+s1);
}
});
String output = String.join("", words);
System.out.println(output);
You need a simple observation, as to why a simple sort wouldn't work. Sorting ["b", "bb", "bba"] in descending order will give you ["bba", "bb", "b"]. However, the word that would occur first in a dictionary would've been ["bb", "bba", "b"].
You need to create a comparator, where you can compare strings x and y as follows:
Create string a = x+y and string b = y+x (basically xy and yx)
Compare a and b. If a>b, that means x should be put first to achieve the correct dictionary order. Otherwise y should be put first.
A simple of doing that would be:
static void printLargest(Vector<String> arr)
{
Collections.sort(arr, new Comparator<String>()
{
#Override public int compare(String X, String Y)
{
String XY = X + Y;
String YX = Y + X;
return XY.compareTo(YX) > 0 ? -1 : 1;
}
});
}
This solution uses no extra space and has O(NlogN) time complexity.
I have two String lists (a and b) that I wanna join with a comma after each element. I want the elements of list a to be first. I'm also stuck on Java 7
I tried the following but it doesn't work:
StringUtils.join(a, ", ").join(b, ", ");
This works :
ArrayList<String> aAndB = new ArrayList<>();
aAndB.addAll(a);
aAndB.addAll(b);
StringUtils.join(aAndB, ", ");
Is there a shorter way of doing this?
You do not need StringUtils By default List toString() displays elements in comma separated format.
System.out.println (new StringBuilder (aAndB.toString())
.deleteCharAt (aAndB.toString().length ()-1)
.deleteCharAt (0).toString ());
The only thing you need to do is delete square brackets
You can use the guava library like so:
String [] a = {"a", "b", "c"};
String [] b = {"d", "e"};
//using Guava library
String [] joined = ObjectArrays.concat(a, b, String.class);
System.out.println("Joined array : " + Arrays.toString(joined));
// Output: "Joined array : [a, b, c, d, e]"
To get short code you could :
String res = String.join(",", a) + "," + String.join(",", b);
Since you are using Java 7, you could write a static method to perform the task.
List<String> a = Arrays.asList("a", "b", "c");
List<String> b = Arrays.asList("d", "e", "f");
String s = join(",", a, b);
System.out.println(s);
List<Integer> aa = Arrays.asList(101, 102, 103);
List<Integer> bb = Arrays.asList(104, 105, 106);
String ss = join(":", aa, bb);
System.out.println(ss);
}
public static <T> String join(String delimiter, List<T>... lists) {
StringBuilder sb = new StringBuilder();
for (List<T> list : lists) {
for (T item : list) {
sb.append(delimiter);
sb.append(item);
}
}
return sb.substring(delimiter.length()).toString();
}
}
This prints.
a,b,c,d,e,f
101:102:103:104:105:106
I have a large List<String> where each String is a sentence containing 1+ "tokens" (prefixed by "a" or "b" and followed by a positive integer):
List<String> tokenList = new ArrayList<String>()
tokenList.add("How now a1 cow.")
tokenList.add("The b1 has oddly-shaped a2.")
tokenList.add("I like a2! b2, b2, b2!")
// etc.
I want to write a function that accepts a vararg list of tokens and will return a subset of the tokenList of String that contain all the token arguments. For instance:
public class TokenMatcher {
List<String> tokenList; // Same tokenList as above
List<String> findSentencesWith(String... tokens) {
List<String> results = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
// Build up the regex... (TODO: this is where I'm going wrong)
for(String t : tokens) {
sb.append(t);
sb.append("|");
}
String regex = sb.toString();
for(String sentence : tokenList) {
if(sentence.matches(regex)) {
results.add(sentence);
}
}
return results;
}
}
Again, the regex has to be constructed in such a way that all the tokens passed into the function have to exist inside the sentence in order for the match to be true. Hence:
TokenMatcher matcher = new TokenMatcher(tokenList);
List<String> results = matcher.findSentencesWith("a1"); // Returns 1 String ("How now a1 cow")
List<String> results2 = matcher.findSentencesWith("b1"); // Returns 1 String ("The b1 has oddly-shaped a2.")
List<String> results3 = matcher.findSentencesWith("a2"); // Returns the 2 Strings with a2 in them since "a2" is all we care about...
List<String> results4 = matcher.findSentencesWith("a2", "b2"); // Returns 1 String ("I like a2! b2, b2, b2!.") because we care about BOTH tokens
The last example (results4) is important because although the "a2" token appears in several sentences, with results4 we are asking the method to give us matches for sentences containing both tokens. This is n-ary conjunctive, meaning that if we specified 50 tokens as parameters, we would only want sentences with all 50 tokens.
The above findSentencesWith example is my best attempt so far. Any ideas?
Given your stated requirements that neither order nor frequency matter, I don't see the need to use regexes at all in this case.
Rather, you can compare every string with all the example tokens that were provided and see if all are contained in the string. If so, it's in the result set. The first time a missing token is detected, that string is removed from the result set.
This sort of code would look something like this:
TokenMatcher.java
package so_token;
import java.util.*;
public class TokenMatcher {
public TokenMatcher(List<String> tokenList) {
this.tokenList = tokenList;
}
List<String> tokenList;
List<String> findSentencesWith(String... tokens) {
List<String> results = new ArrayList<String>();
// start by assuming they're all good...
results.addAll(tokenList);
for (String str : tokenList) {
for(String t : tokens) {
// ... and remove it from the result set if we fail to find a token
if (!str.contains(t)) {
results.remove(str);
// no point in continuing for this token
break;
}
}
}
return results;
}
public static void main (String[] args) throws java.lang.Exception
{
List<String> tokenList = new ArrayList<String>();
tokenList.add("How now a1 cow.");
tokenList.add("The b1 has oddly-shaped a2.");
tokenList.add("I like a2! b2, b2, b2!");
TokenMatcher matcher = new TokenMatcher(tokenList);
List<String> results = matcher.findSentencesWith("a1"); // Returns 1 String ("How now a1 cow")
for (String r : results) {
System.out.println("1 - result: " + r);
}
List<String> results2 = matcher.findSentencesWith("b1"); // Returns 1 String ("The b1 has oddly-shaped a2.")
for (String r : results2) {
System.out.println("2 - result: " + r);
}
List<String> results3 = matcher.findSentencesWith("a2"); // Returns the 2 Strings with a2 in them since "a2" is all we care about...
for (String r : results3) {
System.out.println("3 - result: " + r);
}
List<String> results4 = matcher.findSentencesWith("a2", "b2"); // Returns 1 String ("I like a2! b2, b2, b2!.") because we care about BOTH tokens
for (String r : results4) {
System.out.println("4 - result: " + r);
}
}
}
This results in the following output:
1 - result: How now a1 cow.
2 - result: The b1 has oddly-shaped a2.
3 - result: The b1 has oddly-shaped a2.
3 - result: I like a2! b2, b2, b2!
4 - result: I like a2! b2, b2, b2!
Slightly tweaked, runnable code (mainly around no package name and non-public class, so it'll run on the site) on ideone.
Note: Based on the information you provided, and since the function is accepting a list of tokens, it appears that contains would be sufficient for determining whether or not the token is present. However, if it turns out there are additional constraints on that, such as the token must be followed by a space or one out of a set of punctuation, or something like that, in order to count as a token, then I would recommend using regexes -- on an individual-token basis -- replacing contains with matches and passing in the regex defining what you want surrounding the token.
It may also be desirable to have a function that validates your tokenList that is passed to the findSentencesWith function.
I am brand new to Java :)
I have 2 String lists and I was wondering what would be the most efficient way to compare the two and have a resulting array which contains strings that are not in the other. For example, I have a list called oldStrings and one called Strings. I have seen the Comparator function but don't fully understand how it works, right now I was thinking I could create a for loop, loop through each string and then save that string:
for (final String str : oldStrings) {
if(!strings.contains(str))
{
getLogger().info(str + " is not in strings list ");
}
}
There's going to be up to 200 strings in this list. Would this be the best way to go about this? Thank you!
Collection firstList = new ArrayList() {{
add("str1");
add("str2");
}};
Collection secondList = new ArrayList() {{
add("str1");
add("str3");
add("str4");
}};
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Here is main part
secondList.removeAll(firstList);
System.out.println("Result: " + secondList);
Update:
More sophisticated version of code
Collection<String> firstList = new ArrayList<String>();
firstList.add("str1");
firstList.add("str2");
Collection<String> secondList = new ArrayList<String>();
secondList.add("str1");
secondList.add("str2");
secondList.add("str3");
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Here is main part
secondList.removeAll(firstList);
Update:
To Get acctual difference between both String list go for this.
Set<String> setOne = new HashSet<String>();
Set<String> setTwo = new HashSet<String>();
setOne.add("1");
setOne.add("2");
setOne.add("5");
setTwo.add("1");
setTwo.add("3");
setTwo.add("4");
Set<String> setTwoDummy = new HashSet<String>(setTwo);
setTwo.retainAll(setOne);
setTwoDummy.addAll(setOne);
setTwoDummy.removeAll(setTwo);
System.out.println(""+setTwoDummy);
First, the problem with your solution is that it will only find elements that are in oldStrings and not strings. If you're going with this approach then you need to loop on the other list as well.
If this is not for homework then check out CollectionUtils.disjunction from Apache Commons Collections.
Compare two lists of strings and have a
resulting array which contains strings
that are not in the other.
The description is ambiguous because we don't we don't know if we need just non matching strings from the first list, the second list, or both. Below is pseudo code for both.
for (String str : oldStrings)
{
if(strings.contains(str))
{
intersectionList.add(str);
}
}
oldStrings.removeAll(intersectionList);
strings.removeAll(intersectionList);
result = strings.addAll(oldStrings).toArray();
Or
copyStrings = strings.clone();
strings.removeAll(oldStrings);
oldStrings.removeAll(copyStrings);
result = strings.addAll(oldStrings).toArray();
You should be using Google Guava's Sets utilities.
Set<String> s = Sets.newHashSet("a", "b", "c", "d");
Set<String> t = Sets.newHashSet("f", "g", "a", "c");
Sets.SetView<String> difference = Sets.difference(s, t);
System.out.println(difference); // prints [b, d]