Compare and extract similar strings from 2 arrays in java, without duplication - java

I am trying to extract similar strings from 2 arrays, and I have managed to do so, except they are duplicating. i.e. array 1 {"arrow", "arrow", "sycophant"} and array 2 ("arrow", "sycophant", "bulbasaur"} will give me the output of {"arrow", "arrow" ,"sycophant"}, while I am only trying to get arrow once. Any suggestions?
public static void main(String[] args) {
String[] words1 = { "sycophant", "rattle", "zinc", "alloy", "tunnel", "arrow" };
String[] words2 = { "sycophant", "arrow", "arrow" };
// String prefix = "a";
// String substring = "at";
// char[] letters = { 'a', 'b' };
// String[] output = wordsStartingWith(words1, prefix);
// String[] output = wordsContainingPhrase(words1, substring);
// String[] output = wordsContainingAll(words1, letters);
String[] output = wordsInBoth(words1, words2);
for (int i = 0; i < output.length; i++) {
System.out.println("Words: " + i + " " + output[i]);
}
}
public static String[] wordsInBoth(String[] words1, String[] words2) {
// method that finds and returns common words in two arrays
String[] returnWords;
int countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j])) {
countWords++;
}
}
}
returnWords = new String[countWords];
countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j])
&& !words1[i].equalsIgnoreCase(returnWords[countWords])) {
returnWords[countWords] = words1[i];
countWords++;
}
}
}
return returnWords;
}

One possibility is to store the words that are found in a HashSet, which won't add duplicates.
// method that finds and returns common words in two arrays
public static String[] wordsInBoth(String[] words1, String[] words2) {
Set<String> returnWords = new HashSet<String>();
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j]))
returnWords.add(words1[i]);
}
}
return returnWords.toArray(new String[returnWords.size()]);
}

You want to get the intersection between two lists. The answer to Intersection and union of ArrayLists in Java should point you in the right direction:
public class Test {
public static void main(String... args) throws Exception {
List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C"));
List<String> list2 = new ArrayList<String>(Arrays.asList("B", "C", "D", "E", "F"));
System.out.println(new Test().intersection(list1, list2));
}
public <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if(list2.contains(t)) {
list.add(t);
}
}
return list;
}
}

In case you wonder why this
for (int i = 0; i < words1.length; i++)
for (int j = 0; j < words2.length; j++)
if (words1[i].equalsIgnoreCase(words2[j]) &&
!words1[i].equalsIgnoreCase(returnWords[countWords])
)
returnWords[countWords++] = words1[i];
doesn't work: it only a) attempts to check if words1[i] isn't the b) last word in returnWords.
a)
!words1[i].equalsIgnoreCase( returnWords[countWords] )
is always true, because returnWords[countWords] is always null. When countWords is 0 there are no words added to it yet, and when it is 1, the added word is at returnWords[0]. So you'll need something like this instead:
countWords == 0 || !words1[i].equalsIgnoreCase( returnWords[countWords-1] )
Now it works fine for your input (removed unique words):
String[] words1 = { "arrow", "sycophant" };
String[] words2 = { "arrow", "sycophant", "arrow" };
it outputs
Words: 0 arrow
Words: 1 sycophant
Words: 2 null
b)
For
String[] words1 = { "arrow", "sycophant", "arrow" };
String[] words2 = { "arrow", "sycophant" };
it outputs
Words: 0 arrow
Words: 1 sycophant
Words: 2 arrow
To prevent this, you would have to check whether the word about to be added isn't any of the already-added words:
!contains( returnWords, words1[j] )
This is a simple for-loop, which you know how to do - and there are plenty of examples on this page, so I'll leave that out.

Maybe this will help you. I have changed your algorithm a bit and now it looks like this.
import java.util.Arrays;
public class Distinct {
public static void main(String[] args) {
String[] words1 = { "sycophant", "rattle", "zinc", "alloy", "tunnel",
"arrow" };
String[] words2 = { "sycophant", "arrow", "alloy", "arrow" };
// String prefix = "a";
// String substring = "at";
// char[] letters = { 'a', 'b' };
// String[] output = wordsStartingWith(words1, prefix);
// String[] output = wordsContainingPhrase(words1, substring);
// String[] output = wordsContainingAll(words1, letters);
String[] output = wordsInBoth(words1, words2);
for (int i = 0; i < output.length; i++) {
System.out.println("Words: " + i + " " + output[i]);
}
}
public static String[] wordsInBoth(String[] words1, String[] words2) {
String[] returnWords;
int countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j])) {
countWords++;
}
}
}
returnWords = new String[countWords];
countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j]) && !exists(returnWords, words1[i])) {
returnWords[countWords] = words1[i];
countWords++;
}
}
}
return Arrays.copyOfRange(returnWords, 0, countWords);
}
public static boolean exists(String[] array, String value)
{
if (array.length == 0)
return false;
for(int i = 0; i < array.length; i++){
if (array[i]!= null && array[i].equalsIgnoreCase(value) )
return true;
}
return false;
}
}

Try this.
public static String[] wordsInBoth(String[] words1, String[] words2) {
return Stream.of(words1)
.filter(w -> Stream.of(words2).anyMatch(w::equalsIgnoreCase))
.toArray(String[]::new);
}

After a bit of fiddling around with the (primitive, slow and downright beginner :P) code I found a (messy) solution to my problems. XD
public static String[] wordsInBoth(String[] words1, String[] words2) {
// method that finds and returns common words in two arrays
String[] returnWords = new String[words1.length];
String compare = "";
int countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j]) && words1[i] != compare) {
returnWords[countWords] = words1[i];
compare = returnWords[countWords];
countWords++;
}
}
}
returnWords = new String[countWords];
countWords = 0;
for (int i = 0; i < words1.length; i++) {
for (int j = 0; j < words2.length; j++) {
if (words1[i].equalsIgnoreCase(words2[j]) && words1[i] != compare) {
returnWords[countWords] = words1[i];
compare = returnWords[countWords];
countWords++;
}
}
}
return returnWords;
}
(also, I don't know why, but my method line is not included in the code snippet when I post to Stack)

Related

Splitting string into different arrays of types using regex

What's the easiest and most effective way to spit a string into different arrays of types? Example:
String[] textArr;
String[] numbersArr;
and if possible a String[] doubleArr and a String[] dateArrayz
//the string I want to split
String splitMe = "Tinus has 99 issues and has to pay $2200.50 for 26 on 2016/10/10";
After it's split it should be
String[] textArr = ["Tinus","has","issues","and","to","pay","for","on"];
String[] numbersArr = ["99","26"];
String[] doubleArr = ["2200.50"];
String[] dateArr = ["2016/10/10"];
I might opt for just splitting the input string by space, and then using a pattern match to check each entry to determine where it belongs:
String splitMe = "Tinus has 99 issues and has to pay $2200.50 for 26 on 2016/10/10";
String[] parts = splitMe.split(" ");
List<String> textList = new ArrayList<>();
List<String> numbersList = new ArrayList<>();
List<String> currencyList = new ArrayList<>();
List<String> dateList = new ArrayList<>();
for (String part : parts) {
if (part.matches("\\d*")) {
numbersList.add(part);
}
else if (part.matches("\\$\\d*\\.\\d*")) {
currencyList.add(part);
}
else if (part.matches("\\d{4}/\\d{2}/\\d{2}")) {
dateList.add(part);
}
else {
textList.add(part);
}
}
I didn't attempt to formally extract a double from the currency. And I also chose to use lists rather than arrays to store the various terms, because this will scale better. I will leave it up to you to fill in the details.
You can try something like this:
String splitMe = "Tinus has 99 issues and has to pay $2200.50 for 26 on 2016/10/10";
String[] splitArray = splitMe.split(" ");
System.out.println("splitArray: " + Arrays.toString(splitArray));
String[] tmp = new String[splitArray.length];
int i = 0;
for (String s : splitArray) {
if (s.matches("[A-Za-z]+")) {
tmp[i] = s;
i++;
}
}
String[] textArr = new String[i];
for (int j = 0; j < textArr.length; j++) {
textArr[j] = tmp[j];
}
tmp = new String[splitArray.length];
i = 0;
for (String s : splitArray) {
if (s.matches("[0-9]+")) {
tmp[i] = s;
i++;
}
}
String[] numbersArr = new String[i];
for (int j = 0; j < numbersArr.length; j++) {
numbersArr[j] = tmp[j];
}
tmp = new String[splitArray.length];
i = 0;
for (String s : splitArray) {
if (s.matches("\\$[0-9]+\\.[0-9]+")) {
tmp[i] = s;
i++;
}
}
String[] doubleArr = new String[i];
for (int j = 0; j < doubleArr.length; j++) {
doubleArr[j] = tmp[j];
}
tmp = new String[splitArray.length];
i = 0;
for (String s : splitArray) {
if (s.matches("[0-9]+/[0-9]+/[0-9]+")) {
tmp[i] = s;
i++;
}
}
String[] dateArr = new String[i];
for (int j = 0; j < dateArr.length; j++) {
dateArr[j] = tmp[j];
}
System.out.println("textArr: " + Arrays.toString(textArr));
System.out.println("numbersArr: " + Arrays.toString(numbersArr));
System.out.println("doubleArr: " + Arrays.toString(doubleArr));
System.out.println("dateArr: " + Arrays.toString(dateArr));
Please note that the regex used are not ideal but they work for your case. I used arrays because I thought it is a strict requirement. You can use lists as well which is better.

My sort method and find/count method are messing up and I have no idea what's wrong?

I have to write a program that sorts names alphabetically while removing duplicates and counting the amount of times the names appear and capitalizes all of it. My partner and I have been working on this and have found no way to have the sorting method work properly and have the program find and count the times the names appear. We have to use certain methods to do this...which I linked the pdf down at the bottom. I really want to understand what's wrong and why the output is not coming out right.
public class Names {
/**
* #param args the command line arguments
*/
static ArrayList<String> fnArray = new ArrayList<String>();
static ArrayList<String> lnArray = new ArrayList<String>();
public static void main(String[] args) throws IOException {
// TODO code application logic here
getNames(fnArray, lnArray);
sort(lnArray);
find(fnArray,1);
capitalize(fnArray,lnArray);
}
public static void getNames(ArrayList<String> fn, ArrayList<String> ln) throws IOException {
Scanner kb = new Scanner(System.in);
System.out.println("What file would you like to read from ?: ");
String n = kb.next();
File inputFile = new File(n);
Scanner in = new Scanner(inputFile);
while (in.hasNext()) {
String firstName = in.next();
fn.add(firstName);
String lastName = in.next();
ln.add(lastName);
}
for (int i = 0; i < fnArray.size(); i++) {
System.out.println(lnArray.get(i) + " " + fnArray.get(i));
}
}
public static void capitalize(ArrayList<String> fnArray, ArrayList<String> lnArray) {
String capfn = " ";
String capln = " ";
int i = 0;
int j = 0;
System.out.println("****************Names***************");
while (i < fnArray.size() && j < lnArray.size()) {
capfn = fnArray.get(i);
capln = lnArray.get(j);
String capFname = capfn.substring(0, 1).toUpperCase() + capfn.substring(1).toLowerCase();
String capLname = capln.substring(0, 1).toUpperCase() + capln.substring(1).toLowerCase();
fnArray.set(i, capFname);
lnArray.set(i, capLname);
System.out.println(lnArray.get(j) + ", " + fnArray.get(i));
i++;
j++;
}
}
public static void display(ArrayList<String> names) {
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
}
public static int find(String s, ArrayList<String> a) {
int count = 0;
for (String str : a) {
if (str.equalsIgnoreCase(s))
count++;
}
return count; }
public static void removeDuplicates(ArrayList<String> s) {
for (int j = 0; j < s.size(); j++) {
int i = -1;
while ((i = find(s, j)) >= 0) {
s.remove(i);
}
}
}
public static void backwards(ArrayList<String> names) {
for (int i = names.size() - 1; i > 0; i--) {
names.get(i);
for (int j = 0; j < names.size(); i++) {
if ((names.get(i).equals(names.get(j)))) {
names.remove(i);
}
}
}
}
public static void sort(ArrayList<String> array) {
for (int i = 1; i < array.size(); i++) {
// find the index of the ith smallest value
int s = i - 1;
for (int j = i; j < array.size(); j++) {
if (array.get(j).compareTo(array.get(s)) < 0) {
s = j;
}
}
// swap the ith smallest value into entry i-1
String temp = array.get(i - 1);
array.set(i - 1, array.get(s));
array.set(s, temp);
}
}
public static void showUnique(ArrayList<String> names){
System.out.println("Unique name list contains:");
for(int i=0 ;i< names.size() ;i++){
System.out.println(lnArray.get(i) + " " + fnArray.get(i));
}
}}
You can use the Collections.sort() method to sort an array list; once it is sorted, you will have entries like this:
ArrayList = { "Alpha", "Beta", "Beta", "Gamma", "Theta", "Theta" ... }
The important point to note, however, is that the duplicates will be next to each other in the sorted array.
Finally, if you want to remove duplicates, you can put all the elements of the ArrayList into a Set: set is a data-structure which removes duplicates.
Example:
Set<String> foo = new HashSet<String>( yourArrayList );
EDIT: Use this approach which is both: easy and simple-to-comprehend.
for( int i = 0; i < array.size() - 1; i++ )
{
for( int j = i + 1; j < array.size(); j++ )
{
if( array[i] > array[j] )
{
// Swap the contents of array[i] and array[j].
}
}
}

Java array I need your thought

Given an array of strings, return another array containing all of its longest strings.
For (String [] x = {"serm", "aa", "sazi", "vcd", "aba","kart"};)
output will be
{"serm", "sazi" , "kart"}.
The following code is wrong, What can I do to fix it.
public class Tester {
public static void main(String[] args) {
Tester all = new Tester();
String [] x = {"serm", "aa", "sazi", "vcd", "aba","kart"};
String [] y = all.allLongestStrings(x);
System.out.println(y);
}
String[] allLongestStrings(String[] input) {
ArrayList<String> answer = new ArrayList<String>(
Arrays.asList(input[0]));
for (int i = 1; i < input.length; i++) {
if (input[i].length() == answer.get(0).length()) {
answer.add(input[i]);
}
if (input[i].length() > answer.get(0).length()) {
answer.add(input[i]);
}
}
return answer.toArray(new String[0]);
}
}
I will give you solution, but as it homework, it will be only sudo code
problem with your solution is, you are not finging longest strings, but strings same size or bigger than size of first element
let helper = []
let maxLength = 0;
for each string in array
if (len(string) >maxLength){
maxLength = len(string);
clear(helper)
}
if (len(string) == maxLength)
helper.add(string)
}
return helper;
You can try below code
private static String[] solution(String[] inputArray) {
int longestStrSize = 0;
List<String> longestStringList = new ArrayList<>();
for (int i = 0; i < inputArray.length; i++) {
if (inputArray[i] != null) {
if (longestStrSize <= inputArray[i].length()) {
longestStrSize = inputArray[i].length();
longestStringList.add(inputArray[i]);
}
}
}
final int i = longestStrSize;
return longestStringList.stream().filter(x -> x.length() >= i).collect(Collectors.toList()).stream()
.toArray(String[]::new);
}

String permutation using for loops

I have to print all the possible permutations of the given input string.
Using the code below I get aaaa bbb ccc now in next iteration I want to print aaa aab aac. aba aca and so on. Please guide me about it.
String s = "abc";
char ch;
ArrayList<Character> input = new ArrayList<Character>();
public static void main (String [] args)
{
String s= "abc";
int count ;
char ch;
ArrayList<Character> input = new ArrayList<Character>();
for (int i=0; i < s.length(); i++)
{
ch = s.charAt(i);
input.add(ch);
}
for (int i=0; i <= input.size(); i++)
{
for(int j=0; j < input.size(); j++)
{
System.out.print(input.get(i));
}
System.out.println();
}
}
You can use recursive function. Example
private static String text = "abcd";
public static void main(String[] args) {
loopPattern(text, 0, "");
}
private static void loopPattern(String source, int index, String res) {
if (source == null || source.length() == 0) {
return;
}
if (index == source.length()) {
System.out.println(res);
return;
}
for (int i = 0; i < source.length(); i++) {
loopPattern(source, index + 1, res + source.charAt(i));
}
}
In current implementation, you should use:
for (int i=0; i <= input.size(); i++) {
for(int j=0; j < input.size(); j++) {
for(int k=0; k < input.size(); k++) {
System.out.print(input.get(i));
System.out.print(input.get(j));
System.out.print(input.get(k));
System.out.println();
}
}
}
But IMHO it is better to use s.charAt(i) instead of input.get(i).
A recursive version which is not dependent of the number of characters:
class Test
{
public static void main(String[] args)
{
if(args.length != 1)
{
System.out.println("Usage: java Test <string>");
System.exit(1);
}
String input = args[0];
iterate(input, "", input.length());
}
public static void iterate(String input, String current, int level)
{
if(level == 0)
{
System.out.println(current);
return;
}
for(int i=0; i < input.length(); i++)
{
iterate(input, current + input.charAt(i), level-1);
}
}

Removing a comma at the end of String

I am trying to convert an HashSet into comma seperated delimited String
But the problem is that , i am getting an extra comma at the end of the String also as shown .
Please tell me how can i remove that extra comma at the end of the String .
import java.util.HashSet;
import java.util.Set;
public class Test {
private static Set<String> symbolsSet = new HashSet<String>();
static {
symbolsSet.add("Q1!GO1");
symbolsSet.add("Q2!GO2");
symbolsSet.add("Q3!GO3");
}
public static void main(String args[]) {
String[] a = symbolsSet.toArray(new String[0]);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < a.length; i++) {
sb.append(a[i] + ",");
}
System.out.println(sb.toString());
}
}
Output :
Q3!GOO3,Q2!GO2,Q1!GO1,
Do like this
for (int i = 0; i < a.length - 1; i++) {
sb.append(a[i] + ",");
}
sb.append(a[a.length - 1]);
Try with:
for (int i = 0; i < a.length; i++) {
if ( i > 0 ) {
sb.append(",");
}
sb.append(a[i]);
}
There are many ways you can do this, below is a regex solution using String#replaceAll()
String s= "abc,";
s = s.replaceAll(",$", "");
StringBuffer sb = new StringBuffer();
String separator = "";
for (int i = 0; i < a.length; i++) {
sb.append(separator).append(a[i]);
separator = ",";
}
In your given scenario String.lastIndexOf method is pretty useful.
String withComma= sb.toString();
String strWithoutLastComma = withComma.substring(0,withComma.lastIndexOf(","));
System.out.println(strWithoutLastComma);
String str = sb.toString().substring(0, sb.toString().length()-1);
or append only if not last element
for (int i = 0; i < a.length; i++) {
if ( i > 0 ) {
sb.append(",");
}
sb.append(a[i]);
}
public static void main(String args[]) {
String[] a = symbolsSet.toArray(new String[0]);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < a.length-1; i++) {
//append until the last with comma
sb.append(a[i] + ",");
}
//append the last without comma
sb.append(a[a.length-1]);
System.out.println(sb.toString());
}
Try this :
for (int i = 0; i < a.length; i++) {
if(i == a.length - 1) {
sb.append(a[i]); // Last element. Dont append comma to it
} else {
sb.append(a[i] + ","); // Append comma to it. Not a last element
}
}
System.out.println(sb.toString());
Try this,
for (int i = 0; i < a.length-1; i++) {
if(a.length-1!=i)
sb.append(a[i] + ",");
else
{
sb.append(a[i]);
break;
}
}
public static void main(String args[])
{
String[] a = symbolsSet.toArray(new String[0]);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < a.length; i++)
{
sb.append(a[i] + ",");
}
System.out.println(sb.toString().substring(0, sb.toString().length - 1));
}
OR
public static void main(String args[])
{
String[] a = symbolsSet.toArray(new String[0]);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < a.length; i++)
{
sb.append(a[i]);
if(a != a.length - 1)
{
sb.append(",");
}
}
System.out.println(sb.toString());
}
You could grow your own Separator class:
public class SimpleSeparator<T> {
private final String sepString;
boolean first = true;
public SimpleSeparator(final String sep) {
this.sepString = sep;
}
public String sep() {
// Return empty string first and then the separator on every subsequent invocation.
if (first) {
first = false;
return "";
}
return sepString;
}
public static void main(String[] args) {
SimpleSeparator sep = new SimpleSeparator(",");
System.out.print("[");
for ( int i = 0; i < 10; i++ ) {
System.out.print(sep.sep()+i);
}
System.out.print("]");
}
}
There's loads more you can do with this class with static methods that separate arrays, collections, iterators, iterables etc.
Try with this
for (int i = 0; i < a.length; i++) {
if(i == a.length - 1 )
{
sb.append(a[i]);
} else {
sb.append(a[i] + ",");
}
}

Categories