How can I remove duplicate strings from a string array without using a HashSet?
I try to use loops, but the words not delete.
StringBuffer outString = new StringBuffer("Our, aim, and, isn't, easy, you, you're, actual, and, are, aren't, and, improve, achieving, and, Obviously, and, illumination, are");
wordList = outString.toString().split(", ");
for (i = 0; i < wordList.length; i++) {
for (j = 0; j < wordList.length; j++) {
if((wordList[i]!=wordList[j])&&(j>i)){
t=true;
}
}
if(t==true){
k++;
}
}
String[] wordList1 = new String[k];
wordList = outString.toString().split(", ");
for (i = 0; i < wordList.length; i++) {
(j = 0; j < wordList.length; j++) {
if((wordList[i]!=wordList[j])&&(j>i)){
t=true;
}
}
if(t==true){
wordList1[i]=wordList[i];
}
}
1)
I think you need to use the equals operator. Try
if (!wordList[i].equals(wordList[j])){
instead of !=.
2) Also Kevin is right. You need to set t back to false.
3) Side note as pointed out by others already: To be more efficient you should start the inner loop with
for (j = i+1; j < wordList.length; j++) {
4) Another side note: Your result array is still too long. If you don't want to use a List<String> and it is ok to loose the original array you could go with a solution as suggested by Zim-Zam O'Pootertoot and set the original duplicates to null, add a counter
to count how many null values you assigned, initialize the new array with the correct size and loop a final time over the first array and copy only the non-null values into your new array.
Try this code to remove dup words:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < wordList.length; i++) {
boolean found = false;
for (int j = i+1; j < wordList.length; j++) {
if (wordList[j].equals(wordList[i])) {
found = true;
break;
}
}
// System.out.printf("Checking: [%s]%n", wordList[i]);
if (!found) {
if (sb.length() > 0)
sb.append(' ');
sb.append(wordList[i]);
}
}
System.out.printf("Unique: [%s]%n", sb);
If you are allowed to use Lists, you can define a generic method that does this fairly easily:
public <T> T[] removeDuplicates(final T[] array) {
List<T> noDuplicates = new ArrayList<T>();
for (T arrayElem : array) {
if (!noDuplicates.contains(arrayElem)) {
noDuplicates.add(arrayElem);
}
}
return (T[]) noDuplicates.toArray();
}
You probably want to set t back to false after pulling the value you want:
if(t)
{
wordList1[i]=wordList[i];
t = false;
}
Also this:
if((wordList[i]!=wordList[j])&&(j>i))
Will always return true since strings are immutable (unless you compared a string to an exact reference of itself which you disallow with j>i). You need to change it to say this:
if (!(wordList[i].equals(wordList[j]))&&(j>i))
Using .equals will compared that they contain the same string, not that they point to the exact reference of a string.
Not sure if that's the only problems or not, a bit unclear from what's given.
In your inner loop, initialize j = i + 1
if(wordlist[i] != null && wordlist[i].equals(worldlist[j])) { wordlist[j] = null; }
...and then compact the array when you're finished to remove all null values
How about using a List:
wordList = outString.toString().split(", ");
List<String> finalList = new ArrayList<String>();
for(String val : wordList) {
if(!finalList.contains(val)) {
finalList.add(val);
}
}
A Set would be more efficient, however. If you can't use a List or a Set, and you are forced to remove the duplicates, then you will have to loop through the array each time, which will perform horribly.
Iterate through the array, and store in an auxiliary int[] or List<Integer> the indexes of duplicates that you find with your two for's.
Create a new Array, with size equal to the original one minus the size of the repeated Strings.
Iterate through your original array, if the index isn't on your auxiliary list, set it to your new Array.
The best and most effective method is to suppose arr is the array that contains strings and can have duplicate values:
Arrays.sort(arr);
int l = 0;
for (int a = 0; a < arr.length; a++) {
if (a == arr.length - 1)
l++;// its a unique value
else if (!(a[a + 1].equals(arr[a])))
l++;// its also a unique
}
String newArray[] = new String[l];
l = 0;
for (int a = 0; a < arr.length; a++) {
if (a == arr.length - 1)
newArray[l] = arr[a];
else if (!(a[a + 1].equals(arr[a]))) {
newArray[l] = arr[a];
l++;
}
}
Try this...
public class RemoveDupsStringArray {
public static void main(String[] args) {
String[] withDuplicates = new String[] {"one","one","two","three","one","three","three"};
String[] withoutDuplicates = new String[] {"one","two","three"};
removeDuplicates(withDuplicates);
removeDuplicates(withoutDuplicates);
}
private static void removeDuplicates(String[] array) {
int[] occurence = new int[array.length];
for (int i = 0; i < array.length; i++) {
for(int j=i+1;j<array.length;j++){
if(array[i]==array[j]){
occurence[j]=j;
}
}
}
int resultLength=0;
for(int i=0;i<occurence.length;i++){
if(occurence[i]==0){
resultLength++;
}
}
String[] result=new String[resultLength];
int index=0;int j=0;
for(int i=0;i<occurence.length;i++){
index = occurence[i];
if(index==0){
result[j]= array[i];
j++;
}
}
for(String eachString : result){
System.out.println(eachString);
}
}
}
Related
I am coding a program to output common elements of an array. I've got it working, but not to the standard it should be. Currently I have a function getCommonElements that prints each string index of where the string arrays have a commonality, but I have to return an empty string. I want to only return that string (array3) as a list of all the common elements. Thank you.
--The commented out part is the part that I have working, but want to replace. Currently this runs and gives an out of bounds error and I understand why, just want to change that.--
public class GetCommonElement {
public static String[] getCommonElements(String[] array1, String[] array2){
String[] array3 = {""};
for(int i =0; i < array1.length; i++){
for(int j = 0; j < array2.length; j++){
if (array1[i] == array2[j]){
/*System.out.print(array1[i]);
System.out.printf("\n");*/
String temp = array1[i];
for(int k = 0; k < array2.length; k++){
array3[k] = temp;
}
}
}
}
return array3;
}
TLDR: How do I compare two arrays and output the common elements into the new array.
First of all, you should't be using the == operator to compare objects like String. String objects are cached for short ones, but in general there may be String objects that have the same content but doesn't have the same memory address, so == will give you a false. You should be using the String.equals(Object o) method, or the null safe java.util.Objects.equals(Object o1, Object o2).
In addition, you don't know how many items match in the two arrays, so you don't know the length of your array3 result before the execution of the method. I recomend you to use a Set, or if you want, a List object for the result.
The code of the method might be something like the following:
public static String[] getCommonElements(String[] array1, String[] array2) {
List<String> coincidences = new ArrayList<>(
Math.min(array1.length, array2.length)
);
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array2.length; j++) {
if (Objects.equals(array1[i], array2[j])
&& !coincidences.contains(array1[i])) {
coincidences.add(array1[i]);
}
}
}
return coincidences.stream().toArray(String[]::new);
}
You can see here how to append an array. so you could start with an empty array String[] array3 = {}; and instead of array3[k] = temp; you would do something like
array3 = Arrays.copyOf(array3, array3.length + 1);
array3[array3.length - 1] =temp;
Alternatively you could count the matches then initialize an array of appropriate size. One problem I see with your code is that it will do strange things if multiples exist in each array. For example if the string "blah" existed twice in each array it would match 4 times. So for this reason I would probably do something like this which checks for redundancy:
public class matching{
public static String[] getCommonElements(String[] array1, String[] array2){
boolean[] matches = new boolean[array1.length];
boolean hasAMatch = false;
boolean isRedundant = false;
int nMatches = 0;
for(int i =0; i < array1.length; i++){
isRedundant = false;
for(int i2=0;i2<i;i2++){
if(array1[i]==array1[i2]){
isRedundant = true;
break;
}
}
if(!isRedundant){
hasAMatch = false;
for(int j=0; j < array2.length; j++){
if (array1[i] == array2[j]){
hasAMatch = true;
nMatches++;
break;
}
}
if(hasAMatch){
matches[i] = true;
}
}
}
String[] array3 = new String[nMatches];
nMatches = 0;
for(int i =0; i < array1.length; i++){
if(matches[i]){
array3[nMatches] = array1[i];
nMatches ++;
}
}
return(array3);
}
public static void main(String []args){
String[] a = {"blah","blah","didy","blah blah"};
String[] b = {"blah","ditty","blagh blah"};
String[] c = getCommonElements(a,b);
for(int i =0; i < c.length; i++){
System.out.println(c[i]);
}
}
}
Here is my ArrayList:
[1,2,1,0,3,4]
I'm trying to return this:
[1,2,3,4]
Here is my current attempt:
for (int i = 0; i < myArray.size() - 1; i++) {
if (myArray.get(i) < myArray.get(i + 1)) {
System.out.println("Increasing sequence...");
}
}
However, this is not returning the desired output, any ideas?
You'll have to maintain an index (or value) of the last element that you had printed and store it in some variable. Then, you'll have to use the stored element for every new element and check if is greater than the stored element.
As you have mentioned, the first element has to be anyway printed, no matter what.
Something like this might work:
List<Integer> myArray = Arrays.asList(new Integer[]{1,2,1,0,3,4});
System.out.println(myArray.get(0));
int prevPrint = myArray.get(0);
for (int i = 1; i < myArray.size();i++) {
if (myArray.get(i) > prevPrint) {
System.out.println(myArray.get(i));
prevPrint = myArray.get(i);
}
}
The reason why your program was failing was because you were comparing the adjacent two values only and it was possible that you might have already printed a value which is greater than any of the two adjacent values.
A similar question, but a totally different approach (LIS) exists and can be found here
A slight variant on Parijat's answer to avoid repeating the System.out.println:
for (int j = 0; j < myArray.size();) {
System.out.println(myArray.get(j));
int start = j;
do {
++j;
while (j < myArray.size() && myArray.get(j) <= myArray.get(start));
}
Try this,
public static List<Integer> findIncreasingOrder(int[] nums) {
List<Integer> result = new ArrayList<>();
int MAX = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
int value = nums[i];
if (value >MAX){
System.out.println(value);
MAX = value;
result.add(value);
}
}
return result;
}
I am completely new to programming. Can you give me some tips on how to improve my code?
The problem was:
Given an array of strings, return a new array without the strings that are equal to the target string. One approach is to count the occurrences of the target string, make a new array of the correct length, and then copy over the correct strings.
And my code:
public String[] wordsWithout(String[] words, String target) {
int numberOfTargets = 0;
for (int i = 0; i < words.length; i++){
if ( words[i].equals(target) ) numberOfTargets++;
}
String[] result = new String[words.length - numberOfTargets];
for (int i = 0; i < words.length - numberOfTargets; i++){ // 1
result[i] = "0"; // 1
} // 1
for (int i = 0; i < words.length; i++){
if ( !words[i].equals(target) ){
int j = 0; // 2
while ( !result[j].equals("0") ){ // 2
j++; // 2
} // 2
result[j] = words[i];
}
}
return result;
}
Example of how code works:
wordsWithout(["aa", "ab", "ac", "aa"], "aa") → ["ab", "ac"]
I know that new array of ints is filled by zeros dy default. What about new array of Strings? I had to artificially fill it by zeros in part marked as //1, so that I could "scroll" to the right element, when I have to add elements to my new array in part marked as //2.
My code seems to be kind of awkward. Are there any standard methods or general ways to improve my code?
You don't need to set each element to "0".
Just do this:
public static String[] wordsWithout(String[] words, String target) {
int numberOfTargets = 0;
for (int i = 0; i < words.length; i++){
if ( words[i].equals(target) ) numberOfTargets++;
}
String[] result = new String[words.length - numberOfTargets];
int j =0; // for indices of result
for (int i = 0; i < words.length; i++){
if (!words[i].equals(target) ){
result[j++] = words[i];
}
}
return result;
}
Looks like your code could be simplified a lot by just using an ArrayList.
public String[] wordsWithout(String[] words, String target)
{
ArrayList<String> list = new ArrayList<String>();
for(int i = 0; i < words.length; ++i)
{
if(!words[i].equals(target))
{
list.add(words[i]);
}
}
return list.toArray(new String[0]);
}
Basically instead of calculating the size of the target array and initialising it, you use a list (which is variable in size), put in all the elements you need, and then create a new array from it.
Unrelated to that, please don't invent your own values ("0") to describe a null value - there's a dedicated keyword, null, for that.
Use
for (String s : words) {
if (s.equals(target))
numberOfTargets++;
}
This might be a bit simpler. Using the split string method allows you to create an array with each value separated by white space.
public String[] wordsWithout(String[] words, String target) {
String newStr = "";
for (int i = 0; i < words.length; i++){
if (words[i].equals(target))
continue;
newStr = newStr + words[i] +" ";
}
return newStr.split(" ");
}
I made this code. I think it is wrong.
public void display() {
for (int i = 0; i < tabT.length; i++)
if (tabT[i] != null)
for (int j = 0; j <= i; j++)
if (tabT[i] != tabT[j])
System.out.println(tabT[i].getCar());
}
How do I display elements without redundancy in an array?
If you want to use only arrays, you can do something like this:
Make an temp (helper) array, which will include each element seen so far in tabT. Then, before printing the value, you check if it's not appearing in the helper array (tmp).
For example, if you have values in tabT, and you don't want to print each one more than once:
int[] tabT = {1,2,3,1,1,2,6,7,2,7,1};
int[] tmp = new int[tabT.length];
boolean flag;
for (int i = 0; i < tabT.length; i++) {
tmp[i] = tabT[i];
flag = true;
for (int j = 0; j < tmp.length; j++)
if (tabT[i] == tmp[j] && i!=j) {
flag = false;
}
if(flag)
System.out.println(tabT[i]);
}
Output: [1,2,3,6,7]
You can easily apply this idea to your program, and you'll have each element printed only once:
Cars[] tmp = new Cars[tabT.length]; //Assuming tabT is from type Cars[]
boolean flag = true;
for (int i = 0; i < tabT.length; i++) {
tmp[i] = tabT[i];
if (tabT[i] != null) {
for (int j = 0; j < tmp.length; j++)
if (tabT[i].getCar().equals(tabT[j].getCar()) && i!=j)
flag = false;
if(flag)
System.out.println(tabT[i].getCar());
}
}
This will print each car (or whatever you're printing) only once.
Objects compared via equals() For example
if (!tabT[i].equals(tabT[j]))
you are comparing the references values not the objects
for (int i=0; i< tabT.length; i++) {
boolean f = false;
for (int j=i+1; j <tabT.length; j++)
if (tabT[i].equals(tabT[j])) {
f=true;
break;
}
if (!f)
System.out.println(tabT[i].getCar());
}
this should give you all combinations non-repeating for i and j, so we don't compare them multiple times.
== and != test equality at the object level (i.e. if both instances are the same). What you need is to compare the value represented by each object (e.g. if two strings are equals), then you need to ask whether !tabT[i].equals(tabT[j]), and make the elements of tabT implement equals).
Or convert the array to a set, which removes duplicates.
T[] tabT = ...
Set<T> set = new LinkedHashSet<T>(Arrays.asList(tabT))
for (T t:set) System.out.println(t);
I used a LinkedHashSet because it preserves the order of the elements in the array. Note that you need to implement equals and hashcode.
Put tabT array in a Set. There will be no duplicate items.
Set tabTList = new HashMap(Listjava.util.Arrays.asList(tabT);
Why not trying something like this? (I'm supposing that you are working with String types)
HashSet<String> hashSet = new HashSet<String>();
for (int i = 0; i < tabT.length; i++) {
hashSet.add(tabT[i]);
}
You can't have duplicates into a set, so now you can iterate the set to get the uniques.
java.util.Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()) {
System.out.println((String)iterator.next());
}
You could consider a HashMap if you do want to keep track of duplicate count. Iterate through array once to place objects into the HashMap with their respective counts. Then iterate through the array again checking against the HashMap. This would be O(n) time as opposed to potential O(n^2)
I want to compare two arrays and store the difference in another array
For example the two arrays might be
String[] a1 = { "cat" , "dog" };
String[] a2 = { "cat" , "rabbit" };
The resultant array would be like this
{ "rabbit" }
I use this code, but it does not work
int n = 0;
for (int k = 0; k <= temp.length; k++)
{
for (int u = 0; u <= origenal.length; u++)
{
if (temp[k] != origenal[u] && origenal[u] != temp[k])
{
temp2[n] = temp[k];
System.out.println(temp[u]);
n++;
}
}
}
This should do the trick.
String[] result = new String[100];
Int k = 0;
Boolean test = true;
for(i=0; i < a1.length; i++){
for(j=0; j < a2.length; j++){
if(a2[i].equals(a1[i])) continue;
test = false
}
if(test == false) result[k++] = a1[i];
}
I think that this may be what you are looking for. Note that it will only add to the third 'array' if the value exist in second array but not in first. In your example only rabbit will be stored, not dog (even though dog does not exist in both). This example could possibly be shortened but I wanted to keep it like this so it is easier to see what is going on.
First import:
import java.util.ArrayList;
import java.util.List;
Then do the following to populate and analyze the arrays
String a1[] = new String[]{"cat" , "dog"}; // Initialize array1
String a2[] = new String[]{"cat" , "rabbit"}; // Initialize array2
List<String> tempList = new ArrayList<String>();
for(int i = 0; i < a2.length; i++)
{
boolean foundString = false; // To be able to track if the string was found in both arrays
for(int j = 0; j < a1.length; j++)
{
if(a1[j].equals(a2[i]))
{
foundString = true;
break; // If it exist in both arrays there is no need to look further
}
}
if(!foundString) // If the same is not found in both..
tempList.add(a2[i]); // .. add to temporary list
}
tempList will now contain 'rabbit' as according to the specification. If you necessary need it to be a third array you can convert it to that quite simply by doing the following:
String a3[] = tempList.toArray(new String[0]); // a3 will now contain rabbit
To print the content of either the List or Array do:
// Print the content of List tempList
for(int i = 0; i < tempList.size(); i++)
{
System.out.println(tempList.get(i));
}
// Print the content of Array a3
for(int i = 0; i < a3.length; i++)
{
System.out.println(a3[i]);
}