I am trying to remove elements from String A using an array of String B.
My logic is to convert the string A to an array and then check if A contains the same elements as B and write that data to an empty String, but it doesn't work if B has two or more elements.
Can you tell me what I'm doing wrong?
class Test {
public static void main(String[] args) {
WordDeleter wordDeleter = new WordDeleter();
// Hello
System.out.println(wordDeleter.remove("Hello Java", new String[] { "Java" }));
// The Athens in
System.out.println(wordDeleter.remove("The Athens is in Greece", new String[] { "is", "Greece" }));
// This cat
System.out.println(wordDeleter.remove("This is cat", new String[] { "is" }));
}
}
class WordDeleter {
public String remove(String phrase, String[] words) {
String[] arrayPhrase = phrase.split(" ");
String result = "";
for (int i = 0; i < arrayPhrase.length; i++) {
for (int j = 0; j < words.length; j++) {
if (!arrayPhrase[i].equalsIgnoreCase(words[j]))
result += arrayPhrase[i] + " ";
}
}
return result.trim();
}
}
Output is:
Hello
The The Athens Athens is in in Greece
This cat
You're close but you need to use the helpful .contains() method. This should work for the multi-length set of words. Your nested for loop checked for both words, thus the copying. Also the not-allowed words were only written once, so it infact "worked" but not the way you intended.
class Test {
public static void main(String[] args) {
WordDeleter wordDeleter = new WordDeleter();
// Hello
System.out.println(wordDeleter.remove("Hello Java", new String[] { "Java" }));
// The Athens in
System.out.println(wordDeleter.remove("The Athens is in Greece", new String[] { "is", "Greece" }));
// This cat
System.out.println(wordDeleter.remove("This is cat", new String[] { "is" }));
}
}
class WordDeleter {
public String remove(String phrase, String[] wordsArray) {
List<String> words = Arrays.asList(wordsArray);
String[] arrayPhrase = phrase.split(" ");
String result = "";
for (int i = 0; i < arrayPhrase.length; i++) {
// If the word is not contained in the not allowed array
if(!words.contains(arrayPhrase[i])){
result += arrayPhrase[i] + " ";
}
}
return result.trim();
}
}
Another thing you can do to make it better is use StringBuilder.
Instead of String result = "", use StringBuilder result = new StringBuilder(). And instead of result +=arrayPhrase[i] + " "; use result.append(arrayPhrase[i] + " "); as so:
class Test {
public static void main(String[] args) {
WordDeleter wordDeleter = new WordDeleter();
// Hello
System.out.println(wordDeleter.remove("Hello Java", new String[] { "Java" }));
// The Athens in
System.out.println(wordDeleter.remove("The Athens is in Greece", new String[] { "is", "Greece" }));
// This cat
System.out.println(wordDeleter.remove("This is cat", new String[] { "is" }));
}
}
class WordDeleter {
public String remove(String phrase, String[] words) {
String[] arrayPhrase = phrase.split(" ");
StringBuilder result = new StringBuilder();
for (int i = 0; i < arrayPhrase.length; i++) {
// If the word is not contained in the not allowed array
if(!words.contains(arrayPhrase[i])){
result.append(arrayPhrase[i] + " ");
}
}
return result.toString().trim();
}
}
The most efficient way to remove all occurrences of strings contained in the given array from the given string is to generate a HashSet from the given array and check for every word in the given string, whether it's present in the set or not.
To avoid overheads of string concatenation, we can use StringJoiner.
That's how it can be implemented.
public static String remove(String phrase, String[] words) {
String[] arrayPhrase = phrase.split(" ");
Set<String> wordsToRemove = Arrays.stream(words).collect(Collectors.toSet());
StringJoiner result = new StringJoiner(" ");
for (String word: arrayPhrase) {
if (!wordsToRemove.contains(word)) {
result.add(word);
}
}
return result.toString();
}
And that's how it can be implemented with streams using collector joining():
public static String remove(String phrase, String[] words) {
Set<String> wordsToRemove = Arrays.stream(words).collect(Collectors.toSet());
return Arrays.stream(phrase.split(" "))
.filter(word -> !wordsToRemove.contains(word))
.collect(Collectors.joining(" "));
}
A link to Online Demo
Related
I want to abbreviate names that given names include 3 names or more.
Also, I want to put '.' between them.
Thank you
For example
sam harris dorothy
my expectation output like below
s.h.d
My code like this
public class AbbreviateTwoWords {
public static void main(String[] args) {
String shs = abbrevName("Sam Harris");
System.out.println(shs);
}
public static String abbrevName(String name) {
String[] splitnamelist = name.split(" ");
char[] shortform = new char[10];
String point = ".";
int initial = 0;
for (String i : splitnamelist) {
if (initial % 2 == 0) {
shortform[initial] = i.charAt(0);
initial++;
} else {
shortform[initial]=point;
initial++;
}
return new String(shortform);
}
}
}
why complicate and use char array, im guessing its something with the indexes at any rate just use string and concatenate:
public static String abbrevName(String name) {
String[]splitnamelist=name.split(" ");
String shortform="";
for (String currentName:splitnamelist) {
shortform=shortform+currentName.charAt(0);
shortform=shortform+".";
}
//remove the last dot
if (shortform.length()>0)
{
shortform=shortform.substring(0, shortform.length()-1);
}
return shortform;
}
public class AbbreviateName {
public static void main(String[] args) {
AbbreviateName shs = new AbbreviateName();
shs.abbrevName("sam harris dorothy");
}
public void abbrevName(String name) {
String splitName[] = name.split(" "), seperatedName="";
int i=0; // To remove the last "+" sign.
for(String key : splitName){
seperatedName+=key;
if(i<splitName.length-1) {
seperatedName += "+";
}
i++;
}
int k;
System.out.print(seperatedName.charAt(0)+".");
//First letter always displayed
for(int j = 0,l=0; j<seperatedName.length()-1; j++){
k=j;
if(seperatedName.charAt(j)=='+'){
System.out.print(seperatedName.charAt(++k)+".");
// Letter succeeding "+" will be printed.
}
}
}
}
If you are allowed to use Java 8+ streams, you could create abbreviations like this:
import java.util.*;
import java.util.stream.*;
public class Main {
public static String abbreviate(String input) {
if (null == input || input.isEmpty()) {
// nothing to abbreviate
return input;
}
return Arrays.stream(input.split("[.\\s]+")) // split input line by 1 or more whitespaces or dot
.map(s -> s.substring(0, 1)) // get first letter
.collect(Collectors.joining(".")); // join letters into string with "." delimiter
}
}
In this code a dot "." is also included into delimiters to properly handle an abbreviation existing in the input string.
Test and online demo:
public static void main(String[] args) {
String[] inputs = {
"Jerome K. Jerome",
"Robert Louis Stevenson",
"Charles Lutwidge Dodgeson"
};
for (String s : inputs) {
System.out.printf("'%s' -> '%s'%n", s, abbreviate(s));
}
}
Output:
'Jerome K. Jerome' -> 'J.K.J'
'Robert Louis Stevenson' -> 'R.L.S'
'Charles Lutwidge Dodgeson' -> 'C.L.D'
In Java8, we can do this in a few lines.
String shs = "sam harris dorothy";
String shortform = Arrays.stream(shs.split(" "))
.map(s -> s.substring(0, 1))
.map(s -> s.concat("."))
.collect(Collectors.joining());
This is the output:
System.out.println(shortform); //Output is: s.h.d.
System.out.println(shortform.substring(0, shortform.length()-1)); //Output is: s.h.d
I have a question about how to return the list of sorted anagrams that are placed adjacently in the indexes of a single array. To clarify this:
Array sortedAnagrams:
sortedAnagrams[0] = asp
sortedAnagrams[1] = pas
sortedAnagrams[2] = code
sortedAnagrams[3] = coed
sortedAnagrams[4] = deco
sortedAnagrams[5] = France
From this example, it is clear that my indices "2","3", & "4" have the highest occurring anagram. How do I write a method where I can say these indices contain the highest occurring anagram?
I started of doing this but I don't know how it should continue.
public static String[] getLargestAnagramGroup(String[] stringList){
for (int i = 0; i < stringList.length; i++) {
int j = i + 1;
if (AnagramUtil.areAnagrams(stringList[i],stringList[j]) == true) {
j++;
} else {
i = j;
}
}
return null; // for now
public static void main(String[] args) {
String[] ListOfSortedAnagrams = new String[] {"asp", "pas", "code", "coed", "deco" , "France" }
System.out.print("Most occurring anagrams are: " + AnagramUtil.getLargestAnagramGroup(String[] ListOfSortedAnagrams));
Results:
Most occurring anagrams are: code, coed, deco
You could normalize strings for example sort chars in string and group them by this normalized value.
Have a look at :
public class Anagram {
public static void main(String[] args) {
String[] listAnagrams = new String[]{"asp", "pas", "code", "coed", "deco", "France"};
Map<String, List<String>> countMap = new HashMap<>();
for (String str : listAnagrams) {
String normalized = normalize(str);
List<String> strings = countMap.getOrDefault(normalized, new ArrayList<>());
strings.add(str);
countMap.put(normalized, strings);
}
Optional<Map.Entry<String, List<String>>> max = countMap.entrySet().stream()
.max(Comparator.comparingInt(entry -> entry.getValue().size()));
System.out.print("Most occurring anagrams are: " + max.get().getValue());
}
private static String normalize(String inputString){
char[] tempArray = inputString.toCharArray();
Arrays.sort(tempArray);
return new String(tempArray);
}
}
Output:
Most occurring anagrams are: [code, coed, deco]
PS: It could be refactored with stream group but I think it will be less readable.
Update:
Here is stream group version:
public class Anagram {
public static void main(String[] args) {
String[] listAnagrams = new String[]{"asp", "pas", "code", "coed", "deco", "France"};
Optional<Map.Entry<String, List<String>>> maxNormalised = Arrays.stream(listAnagrams)
.collect(Collectors.groupingBy(Anagram::normalize))
.entrySet().stream()
.max(Comparator.comparingInt(entry -> entry.getValue().size()));
System.out.print("Most occurring anagrams are: " + maxNormalised.get().getValue());
}
private static String normalize(String inputString){
char[] tempArray = inputString.toCharArray();
Arrays.sort(tempArray);
return new String(tempArray);
}
}
I want to separate words and print them in a single line with a hyphen(-) in between. I have written the following code but it only prints the last word followed by a hyphen i.e. the output is carrot-. I don't understand why and what changes do I make to get the desired output?
public class SeparatingWords {
public static void main(String[] args) {
String str = "apple banana carrot";
System.out.println(separatingWords(str));
}
public static String separatingWords(String str) {
String[] words = str.split(" ");
String result = null;
for (int i = 0; i < words.length; i++) {
result=words[i]+"-";
}
return result;
}
}
Instead of calling a split and concatenating the string, why can't you directly call replaceAll directly to achieve your goal. This will make your code simple.
String result = str.replaceAll(" ", "-");
Below is sample modified code of yours. Hope this helps
public class Sample {
public static void main(String[] args) {
String str = "apple banana carrot";
System.out.println(separatingWords(str));
}
public static String separatingWords(String str) {
String result = str.replaceAll(" ", "-");
return result;
}
}
If you want to perform any other operation based on your requirement inside the method, then below should work for you. As suggested by #Moler added += and initialized the result object
public static String separatingWords(String str) {
String[] words = str.split(" ");
String result = ""; // Defaulted the result
for (int i = 0; i < words.length-1; i++) {
result += words[i] + "-"; // Added a +=
}
result += words[words.length - 1];
return result;
}
public class SeparatingWords
{
public static void main(String[] args)
{
String str="apple banana carrot";
System.out.println(separatingWords(str));
}
public static String separatingWords(String str)
{
String[] words=str.split(" ");
String result="";
for(int i=0;i<words.length;i++)
{
result += words[i]+"-";
}
return result;
}
}
Try this code:
public class SeparatingWords
{
public static void main(String[] args)
{
String str="apple banana carrot";
System.out.println(separatingWords(str));
}
public static String separatingWords(String str)
{
String[] words=str.split(" ");
String result=words[0];
for(int i=1;i<words.length;i++)
{
result=result+"-"+words[i];
}
return result;
}
}
You could use s StringBuilder, append the single word and a hyphon and at the last word, you just append the word:
public class SeparatingWords {
public static void main(String[] args) {
String str = "apple banana carrot";
System.out.println(separatingWords(str));
}
public static String separatingWords(String str) {
String[] words = str.split(" ");
StringBuilder resultBuilder = new StringBuilder();
for (int i = 0; i < words.length; i++) {
resultBuilder.append(words[i]);
if (i != words.length - 1) {
resultBuilder.append("-");
}
}
return resultBuilder.toString();
}
}
String[] words = str.split(" ");
// perform operations on individual words
return String.join("-", words);
Is there any helper method or utility that actually gives me union of two strings.
For instance, if i have two strings as below:
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
I'm looking for a solution which will take above two strings as input and outputs the result as below:
General syntax: s1.{method/utility}(s2);
output : Isabella,tom,hardy,victor,smith
First, there is no method or utility provided by JDK to address the problem so straight forward.
Second, just for this simple utility importing a 3rd party jar or dependency is not a wise choice.
In this case its always a wise choice to write your own method of purpose.
public static String mergeString(String s1, String s2) {
//check for null as the method doesnt fall in NPE
if(s1 == null || s2 == null) {
return null;
}
//split the given String to some list
List<String> s1List = Arrays.asList(s1.split(","));
List<String> s2List = Arrays.asList(s2.split(","));
//get a Set and add the list items to it. LinkedHashSet
//is used to maintain the given order.
Set<String> stringSet = new LinkedHashSet<>(s1List);
stringSet.addAll(s2List);
//Then join them using java 8 provided Utility
return String.join(",", stringSet);
}
NB: as you mentioned in the comments you may need this type of utility only once in your project. But despite, this logic should be separated from out of your business method. This will make your code more clean and readable.
You can use org.springframework.util.StringUtils
Add a maven dependency spring-core:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
Use StringUtils:
public static void main(String[] args) {
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
String[] outputArr=StringUtils.mergeStringArrays(s1.split(","),s2.split(","));
String output=StringUtils.arrayToCommaDelimitedString(outputArr);
System.out.println(output);
}
Output:
Isabella,tom,hardy,victor,smith
public void unionString(String s1, String s2){
String[] s1Ar = s1.split(",");
String[] s2Ar = s2.split(",");
HashSet<String> set = new HashSet<String>();
for(int i=0;i<s1Ar.length;i++){
set.add(s1Ar[i]);
}
for(int i=0;i<s2Ar.length;i++){
set.add(s2Ar[i]);
}
Iterator<String> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
Here's a method that will do the union of two strings. You can also pass it a boolean flag to dictate case sensitivity.
public static String union (String s1, String s2, boolean caseInsensitive)
{
// if either string is null, union is the other string
if (s1 == null)
return s2;
if (s2 == null)
return s1;
// use linked set to keep ordering
Set<String> unique = new LinkedHashSet<>();
// put all words from string 1 into the set
for (String word : s1.split(","))
{
word = word.trim(); // remove surrounding space on word
if (caseInsensitive)
{
word = word.toLowerCase();
}
unique.add(word);
}
// put all words from string 2 into the set
for (String word : s2.split(","))
{
word = word.trim(); // remove surrounding space on word
if (caseInsensitive)
{
word = word.toLowerCase();
}
unique.add(word);
}
// get back the format of comma delimiter for the union
String ret = unique.toString().replaceAll("[\\[\\] ]", "");
return ret;
}
Usage:
public static void main(String args[])
{
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
String union = union(s1, s2, false);
System.out.println(union);
}
Outputs:
Isabella,tom,hardy,victor,smith
You Can Use LinkedHashSet which maintains the insertion Order to get desired output.Below is my code:
public class UnionJava {
static LinkedHashSet<String> hashSetString = new LinkedHashSet<>();
static String s1 = "Isabella,tom,hardy"; static String s2 = "Isabella,tom,hardy,victor,smith";
public static void main(String args[]){
String[] set1 = s1.split(","); String[] set2 = s2.split(",");
for(int i=0; i< set1.length;i++){
hashSetString.add(set1[i]);
}
for(int i=0;i<set2.length;i++){
hashSetString.add(set2[i]);
}
int j=0;
for(Iterator i = hashSetString.iterator(); i.hasNext();){
if(j==0){
System.out.print(i.next());
j++;
}else{
System.out.print(","+i.next());
}
}
}
}
A short version with no sanity checks using LinkedHashSet.
public void printUnion() {
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
Set<String>mySet = new LinkedHashSet<>();
mySet.addAll(Arrays.asList(s1.split(",")));
mySet.addAll(Arrays.asList(s2.split(",")));
mySet.stream().forEach(System.out::println);
}
With the java api, you might try :
public class StringTest {
private String string1 ="";
private String string2 ="";
private List<String> array1 = new ArrayList<String>();
private List<String> array2 = new ArrayList<String>();
private String[] stringa1;
private String[] stringa2;
private int output3 = 0;
private int output4 = 0;
public static void main(String[] args) {
new StringTest().startApp();
}
private void startApp() {
string1 = "Isabella,tom,hardy";
stringa1 = string1.split("\\s+"); //array to split
string2 = "Isabella,tom,hardy,victor,smith";
stringa2 = string2.split("\\s+");
for(int o = 0; o<stringa1.length; o++) {
array1.add(stringa1[o]); //adding to arraylist
}
for(int o = 0; o<stringa2.length; o++) {
array2.add(stringa2[o]);
}
for(int outP = 0; outP<array2.size()+array1.size(); outP++) {
for(output4 = 0; output4<array2.size(); output4++) { //iterating and removing double elements
for(output3 = 0; output3<array1.size(); output3++) {
if(array1.size() > array2.size() && array2.get(output4).equalsIgnoreCase(array1.get(output3))) {
array1.remove(array1.get(output3));
}
if(array1.size() < array2.size() && array2.get(output4).equalsIgnoreCase(array1.get(output3))) {
array2.remove(array2.get(output4));
}
}
}
}
array1.addAll(array2); //merging the lists
for(String outPres1 : array1) {
result += " " + outPres1;
}
System.out.println("This is the output: " + result);
}
String s1 = "Isabella,tom,hardy";
String s2 = "Isabella,tom,hardy,victor,smith";
Set<String> result = new TreeSet<String>();
result.addAll(Arrays.asList(s1.split((","))));
result.addAll(Arrays.asList(s2.split((","))));
System.out.println(result);
Well, someone's got to provide a streams solution:
Stream.of(s1, s2)
.flatMap(Pattern.compile(",")::splitAsStream)
.distinct()
.collect(Collectors.joining(","))
I am working on my own personal app for minecraft. I would forget what recipe I need, and I would just search, and have it display the recipe.
Now, I have the list and search function with it being alphabetical. Now I am manually adding images, and everything else I need. BUT I think it would be more efficient if I had a array string like this
String test1[] = { "diamond", "Iron", "Leather" };
String test2[] = { "Leggings", "Boots", "Helmet", "Chestplate" }
and in my list view I want the end result to be like this.
Diamond leggings
Diamond boots
Diamond Helmet
Diamond Chestplate
Iron Leggings
...
...
Gold Leggings
...
...
...
What would I need to do to achieve that? I think it would be ineffecient if I did it like this
test3.add("Diamond Chestplate")
test3.add("Diamond boots")
etc..
..
...
and end up having big list instead where I can combine them.
Use 2 nested for loops to merge the arrays:
String test1[] = {"Diamond", "Iron", "Leather"};
String test2[] = {"Leggings", "Boots", "Helmet", "Chestplate"};
List<String> merged = new ArrayList<String>();
for (String str1 : test1) {
for (String str2 : test2)
merged.add(str1 + " " + str2);
}
System.out.println(merged);
If I understand your question, you could do with nested For-Each Loop(s) like
String test1[] = { "Diamond", "Iron", "Leather" };
String test2[] = { "Leggings", "Boots", "Helmet", "Chestplate" };
List<String> al = new ArrayList<>();
for (String i : test1) {
for (String j : test2) {
StringBuilder sb = new StringBuilder(i);
sb.append(' ').append(j);
al.add(sb.toString());
}
}
System.out.println(al);
I am curious to know that If, I can achieve it in a single loop.
How to do it, and finally I have done it.
private static String test1[] = {"Diamond", "Iron", "Leather"};
private static String test2[] = {"Leggings", "Boots", "Helmet", "Chestplate"};
public static void doInSingleLoop() {
int maxLength = test1.length * test2.length;
List<String> al = new ArrayList<String>();
for (int i = 0; i < maxLength; i++) {
String t1 = test1[i / test2.length];
String t2 = test2[i % test2.length];
StringBuilder sb = new StringBuilder(t1);
sb.append(' ').append(t2);
al.add(sb.toString());
}
System.out.println(al);
}
Check below example.
public static void main(String[] args) {
String firstNameArr[] = { "diamond", "Iron", "Leather" };
String lastNameArr[] = { "Leggings", "Boots", "Helmet"};
List<String> fullNameList = new ArrayList<String>();
for (String firstname : firstNameArr) {
for(String lastName : lastNameArr){
fullNameList.add((firstname+" "+lastName));
}
}
}