comparing elements of array - java

please help me with this. i want to scan array1 through elements of array2 and disregard the elements of array2 if it's found in array1. so a list of fruits will only be left. but the output shows : ball, pencil. where i would want it to display only the elements in fruits. thanks for your help
import java.util.*;
public class CountFruits
{
public static void main(String args[])throws Exception
{
String array1[] = {"apple", "mango", "orange", "banana", "ball", "pencil"};
String array2[] = {"ball", "pencil"};
List<String> fruits = new ArrayList<String>();
for(int x = 0; x < array1.length; x++)
{
for(int y = 0; y < array2.length; y++)
{
if(array1[x].equals(array2[y]))
{
System.out.println(array1[x] + "\t" + array2[y]);
if(!fruits.contains(array1[x]))
{
fruits.add(array1[x]);
}
}
}//end for
}//end for
System.out.println("fruits: " +fruits);
}
}

First, I am assuming that this is a homework of sorts, so I wouldn't spoil your exercise by fixing your code.
Here is the idea: you need to create a boolean variable that indicates if the nested loop has found anything or not, set it to "not found" going into the loop, and checking it after the loop. If the loop indicates that an item has been found, skip it; otherwise, add it. Remember, you can do it only after the nested loop has finished, so calling fruits.add inside the nested loop is premature.
boolean found = false;
for(int y = 0; !found && y < array2.length; y++) {
found |= array1[x].equals(array2[y]);
}
if (!found) ...

You need to add the array1[x] to your list if it is NOT in array2[x]:
if (array1[x].equals(array2[y])) {
System.out.println(array1[x] + "\t" + array2[y]);
} else {
fruits.add(array1[x]);
}
But you will have duplicates. You can add a condition if(!fruits.contains(...)) before adding.
You could simplify your code by using the following algorithm:
add all the items in array1 to a list
remove the items in array2 from the list

The if statement if(array1[x].equals(array2[y])) will only be true for ball and pencil, so the fruit array will only add ball and pencil.
You could set the fruit array to hold all of array1 and then, if your if statement is true, remove that element from fruit the array.
or, you could set a boolean isFruit = true (in the outer for loop).
Then, if your if statement if(array1[x].equals(array2[y])) passes, set isFruit to false.
After the iteration of the inner loop, if isFruit is true, add it to the fruit array.
for(int x = 0; x < array1.length; x++)
{
boolean isFruit = true;
for(int y = 0; y < array2.length; y++)
{
if(array1[x].equals(array2[y]))
{
System.out.println(array1[x] + "\t" + array2[y]);
isFruit = false;
}
if(isFruit)
{
fruits.add(array1[x]);
}
}//end for loop
}//end for loop

The best approach would be, if you are using an IDE, step through the code, see where the logic fails. If you are not using a debugger, then put some System.out.println statements into the code. Then you can determine where the logic fails.
The other solution is to attempt the first solution I gave. That is, have the fruit array hold all of array1 and then remove elements that are found in array2

There are two flaws in your logic
1)Here You are adding the elements which should not be added in fruits list.
So you will have to check the elements which are not part of array2 and those should be added.So you may write that logic in else part.
2)You are checking each time whether the element already present in fruits list,instead of that use Set.It will disallow duplicate entries

Related

What if the declared variable in for each loop will print outside of the foor loop

I tried for each loop to find duplicates in an array, if I printing the variable "i" outside of the for each loop, it is providing unexpected output.
Expected: Related errors as like the variable is not declared(as the declared variable is local)
package Login;
public class DupsArray {
public static void main(String[] args) {
int[] a = {1, 2, 3, 3};
int length = a.length;
for (int i : a) {
for (int j = i + 1; j <= length - 1; j++) {
if (a[i] == a[j]) {
System.out.println("Found duplicate" + a[i]);
break;
}
System.out.print(i);
}
}
}
}
11Found duplicate3
You are using i to iterate the values (not indexes) of array a and j to iterate indexes.
Suggestion: instead of using an array you can use an ArrayList and make you code much simpler:
Iterate the list and for any item compare array.indexOf(item) with array.lastIndexOf(item) - if they're different you found a duplicate!
I think you should do it without an enhanced for-loop, because index comparison is needed to avoid false positives, e.g. you compare element i == 3 to element a[j] == 3, which might be the same, but how do you want to determine that?
To get around it, you would need an indexOf, so it would boil down to index comparison again.
I would use two classic for-loops and compare the indexes, skipping equal ones:
public static void main(String args[]) throws Exception {
// the source to be investigated
int[] a = {1, 2, 3, 3};
// a container for duplicates found
Set<Integer> dups = new HashSet<>();
// iterate your elements of the source array
for (int i = 0; i < a.length; i++) {
// compare each one to the others
for (int j = i + 1; j < a.length; j++) {
// find out if the elements are equal
if (a[i] == a[j]) {
// if they are, add it to the set of duplicates
dups.add(a[i]);
// as an alternative, you could print them here, too
// System.out.println("Duplicate found: " + a[i]);
}
}
}
// print the duplicates found
System.out.println("Duplicates found: ");
dups.forEach(d -> System.out.println(d));
}
Please read the code comments and note that you don't have to store the duplicates in case you just want to print them. Storing is needed for further processing or printing it some time later, maybe on demand.

2d array check the rows value with an if statement

So I am trying to loop through the rows of a 2d array to check the if the row matches the property of a method. How can I use an if to just check the row? This is my code
public void recordWhiplashPoints(ConnectionToClient client, int vote){
int[][] votecount = new int[game.getPlayers().length][0];
outside:
if(game.getRecordedAnswers() <= game.getPlayers().length){
for (int i = 0; i < game.getPlayers().length; i++) {
for (int q = 0; q < votecount.length; q++) {
if(votecount[q] == vote){
//do stuff
}
}
}
}
}
So where votecount[row] is. Can I compare that with the property vote some how?
So for two dimensional arrays, which is basically just an array of arrays, you get a member array using something like votecount[i], and you get a member of that array with votecount[i][q]. I think the following is the code you want:
int[][] votecount = new int[game.getPlayers().length][0];
outside:
if(game.getRecordedAnswers() <= game.getPlayers().length){
for (int i = 0; i < length; i++) {
// note that we need to compare against the array votecount[i]
for (int q = 0; q < votecount[i].length; q++) {
// here we access the actual element votecount[i][q]
if(votecount[i][q] == vote){
//do stuff
}
}
}
}
Not sure if this is what you're looking for, but one way to do so would be to use for-each loops
public void recordWhiplashPoints(ConnectionToClient client, int vote){
int[][] votecount = new int[game.getPlayers().length][0];
outside:
if(game.getRecordedAnswers() <= game.getPlayers().length){
for (int[] i : votecount) {
for (int q : i) {
if(q == vote){
//do stuff
}
}
}
}
}
Essentially the first for-each loop goes through each array the 2d votecount array, and then the second for-each loop goes through each of those 1D arrays. If you have any questions just ask.
However, I don't understand how your second if statement will be true, as you never change votecount from anything other that the default, which is a 2D array filled with 0's.

Remove duplicates in ArrayList - Java

I have some problem with my Java code. I'm supposed to use loops and not any other method.
Say that my ArrayList contains of
[Dog Cat Dog Dog Cat Dog Horse]
My goal is also to remove the copies of Dog and Cat so my final results equals
[Dog Cat Horse]
public void removeDouble(){
int counter = 0;
for (int i = 0 ; i < animals.size(); i++) {
for (int j = 1+i; j < animals.size() ; j++)
//don't start on the same word or you'll eliminate it.
if ( animals.get(j).equals( animals.get(i) ) ) {
animals.remove(animals.get(j));
counter++;
}
}
}
It feels like the "logic" is correct but my code does not work very well. Can somebody help me a little?
You can do like this.
ArrayList<String>list=new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("A");
System.out.println("Before "+list); // output[A,B,C,A]
Set<String> listWithoutDuplicates = new LinkedHashSet<String>(list);
list.clear();
list.addAll(listWithoutDuplicates);
System.out.println("list without duplicates : " + list);// output[A,B,C]
The logic for the inner loop is incorrect.
You will skip items every time you have the same item appear consecutively in the list.
Say you had "dog", "dog", "dog", "cat". When you remove the "dog" at index 1, the list now becomes "dog", "dog", "cat".
The problem is that your "j" index is now incremented to 2 so the next test will access the "cat" item, not the "dog" item. So every time you remove an item you are skipping the next item in the list which is why you get inconsistent results.
The solution is to either:
decrement the j variable every time you remove an item
start the inner loop from the end of the list and count down backwards toward 0.
It would be simpler to start from the end of the list and decrement the counter. After removing the double at i, we can break without checking the whole string, because further doubles will be detected when i reaches j.
for(int i=animals.size()-1; i>0; i--) {
for(int j=i-1; j>=0; j--) {
if(animals.get(i).equals(animals.get(j))) {
animals.remove(i);
break;
}
}
}
Moving backwards avoids the problem as you move forward the indexes have changed because you removed earlier elements (and you failed to adjust the index to take that into account).
Another problem with your logic you were using remove(object) rather than remove(index), which causes the first matching object to be removed. However, based on expected output, you want to preserve the order of the first matching objects. So instead you should have removed the last matching object, via index.
If you want to move forward rather than backwards, but you don't wish to make adjustments to the index after a removal, it is possible to make use of iterator's remove method:
for(int i=0; i<animals.size()-1; i++) {
ListIterator<?> iter = animals.listIterator(i+1);
while(iter.hasNext()) {
if(animals.get(i).equals(iter.next())) {
iter.remove();
}
}
}
Unfortunately the outer loop here cannot use an iterator because that would result in a ConcurrentModificationException.
Finally, you could also use a subList to solve it with a single explicit loop:
for(int i=0; i<animals.size()-1; i++) {
animals.subList(i+1, animals.size()).removeIf(animals.get(i)::equals);
}
In Java 8 we can use Stream API to remove duplicates, Like below snippet.
List<String> uniqueAnimal = animal.stream().distinct().collect(Collectors.toList());
Working Example.
import java.util.*;
import java.util.stream.Collectors;
public class MyClass {
public static void main(String args[]) {
List<String> animal = new ArrayList<>();
animal.add("Dog");
animal.add("Cat");
animal.add("Dog");
animal.add("Dog");
animal.add("Cat");
animal.add("Dog");
animal.add("Horse");
List<String> uniqueAnimal = animal.stream().distinct().collect(Collectors.toList());
System.out.println("animal => " + animal);
System.out.println("uniqueAnimal => " + uniqueAnimal);
}
}
With Java 8 stream you can do as follows:
public class RemoveDuplicates {
public static void main(String[] args) {
removeDuplicateElements(Arrays.asList("Dog","Cat","Dog","Dog","Cat","Dog","Horse"));
}
private static void removeDuplicateElements(List<String> animalList)
{
animalList.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);
}
}
Your removing the items as you are iterating over them, have an array that holds indexes, and when you find a double, add the index to the indexes array. Iterate over the indexes array and delete from the animals arraylist.
Your current code -
for (int i = 0; i < animals.size(); i++) {
for (int j = 1 + i; j < animals.size(); j++)
if (animals.get(j).equals(animals.get(i))) {
animals.remove(animals.get(j)); // this would remove the current element only if the previous element is same as the current element
// since the index `j` would change post that
}
}
}
A simple way to do this is
animals.stream().distinct().collect(Collectors.toList()).forEach(System.out::print);
Or using -
Set<String> distAnimal = new HashSet<>(animals);
System.out.println(Arrays.toString(distAnimal.toArray()));
Thanks for all the answers. I still have a few problems, this is what i have came up with:
int counter =0;
for(int i = 0 ; i < animals.size() ; i++){
for(int j = animals.size() -1 ; j>i ; j--){
if(animals.get(j).equals(animals.get(i))){
counter++;
}
}
}
System.out.println(counter);
}
So now I'm starting the inner loop from the end of the ArrayList. Priority right now is only the get the loop working and then add remove etc.
Cheers!

Taking data from one array to create another. What's wrong with this loop?

I am working on an assignment where I need to create two arrays, then look through them and create a new array that holds any values inside of both the first two. Originally, I was close to accomplishing this by making an arraylist but my lab professor told me that wasn't allowed so I needed to re-start and didn't have enough time to figure out the solution.
If you'd like to see the whole code I have now: http://pastebin.com/thsYnj2z
I am really struggling with this loop here:
for(int i = 0 ; i < Xarr.length ; i++){
for(int j = 0 ; j < Yarr.length ; j++)
//Compare. If the two are the same, they go inside of A.
if (Xarr[i] == Yarr[j]){
ArrA[k] = Xarr[i];
k++;
System.out.println(ArrA[k]);
break;
}
My output is remaining 0 for my ArrA[k] array. I can't seem to trouble shoot this issue on my own.
try making these changes
for(int i = 0 ; i < Xarr.length ; i++){
for(int j = 0 ; j < Yarr.length ; j++)
//Compare. If the two are the same, they go inside of A.
if (Xarr[i] == Yarr[j]){
ArrA[k] = Xarr[i];
System.out.println(ArrA[k]); // or print them all later
k++;
break; // break to outer loop
}
}
}
note
Assuming OP has correctly initialized ArrA
note2
Assuming that only unique values are required, hence the breaking
Does your solution require that no values are duplicated in ArrA? Or are duplicate values allowed? For example, if some values occur multiple times in each array, you could get multiple matches on the same number.
If duplicates aren't a problem:
for(int i = 0 ; i < Xarr.length ; i++){
for(int j = 0 ; j < Yarr.length ; j++){
//Compare. If the two are the same, they go inside of A.
if (Xarr[i] == Yarr[j]){
ArrA[k] = Xarr[i];
System.out.println(ArrA[k]);
k++;
}
}}
As I understand it, the problem is to take 2 arrays, and produce a third array which is a Union of the first 2. Union of 2 sets being the subset of the values found in both sets.
Your code was missing some braces, so put those back in there. Also you wont want to print the k+1th item after you just put a value in ArrA[k] im assuming.
Otherwise you were pretty much there. The break terminates the inner loop and allows the outer loop to increment i and continue on. This is because you have already found a match, no need to continue searching, just move onto the next index in Xarr.
Algorithm goes like this: For each value in X, search Y for a match. If it is found, add this value to A.
for(int i = 0 ; i < Xarr.length ; i++) {
for(int j = 0 ; j < Yarr.length ; j++) {
//Compare. If the two are the same, they go inside of A.
if (Xarr[i] == Yarr[j]){
ArrA[k] = Xarr[i];
System.out.println(ArrA[k]);
k++; //you probably want to increment k after you add to ArrA, not before
break;
}
}
}
public static void main(String... args){
int[] xArr = {1, 1,1,1,1,1};
int[] yArr = {1, };
int[] kArr = new int[xArr.length > yArr.length ? xArr.length : yArr.length];
int k = 0;
for(int x = 0; x < xArr.length; x++){
for(int y = 0; y < yArr.length; y ++){
int xNum = xArr[x];
int yNum = yArr[y];
if(xNum == yNum) kArr[k++] = xNum;
}
}
int[] resizedKArr = new int[k];
for(int i = 0; i < resizedKArr.length; i++) resizedKArr[i] = kArr[i];
Arrays.sort(resizedKArr);
for(int x : resizedKArr) System.out.println(x);
}
First, xArr and yArr are given some random numbers, and then kArr is initialized with the size of the lagest array we are comparing with to ensure the array has enough space to hold similar values.
Then, in the next section we do a loop inside of a loop to compare the values against each other and if they are similar then k++ and set the next value in the array. This goes on until the loops are completed, notice there really is never a need to break from either loop until all values are compared. At that point the loops break themselves and move on to the next bit of code.
The last section is just to create an array of the same size as k and move the values over, I don't know the requirements of your studies, although when using primitives like this you may want to do this in case you have a matching 0 as a number. Otherwise you'll have a ton of 0s filling the empty spaces of your array.
And lastly, we just sort the array for good measure and print it out.
Hope I've answered your question and you get something out of this post!
The problem is printing ArrA[k] after k++. Try increasing line after print.

SelectionSort implemented with Generic Method - Wrong Results

I'm working through Deitel & Deitel's "Java - How To Program" and I'm stumped on why this implementation I came up with of a generic selection sort method is not working. I'm sure I must be missing some small detail, but after researching the API and a few resources on Generics, I'm coming up cold. While the program runs and performs some kind of sort, it definitely does NOT come out sorted in numerical order! I can't tell if I'm misunderstanding Generics, or just the selection sort algorithm. Any help would be appreciated!
The output I receive on running the selection sort on the intArray is:
0, 1, -23, 7, 54
The output for the floatArray after the sort is:
-1.1, -10.3, 0.4, 4.5
UPDATE I just tried this without using negative values and it sorts fine, what is that about???
Here is the complete Sorter class that performs the selection sort:
import java.util.Arrays;
import java.util.ArrayList;
public class Sorter {
public static void main(String[] args) {
Integer[] intArray = {1, 7, -23, 54, 0};
Float[] floatArray = {0.4f, -10.3f, 4.5f, -1.1f};
ArrayList<Integer> intList = new ArrayList<>(Arrays.asList(intArray));
ArrayList<Float> floatList = new ArrayList<>(Arrays.asList(floatArray));
System.out.printf("Lists before selectionSort: %n%s%n%s%n%n",
intList, floatList);
selectionSort(intList);
selectionSort(floatList);
System.out.printf("Lists after selectionSort: %n%s%n%s%n%n",
intList, floatList);
}
public static <T extends Comparable<T>> void selectionSort(ArrayList<T> list) {
// helps determine whether or not a swap will occur
boolean needsSorting = false;
// keeps track of the index of the smallest value
int smallest = 0;
// outer for walks the portion of the list that will be swapped
for (int i = 0; i < list.size() - 1; i++) {
// inner for searches for a smaller value than the front of list
for (int j = i + 1; j < list.size(); j++) {
// if the inner value is less than the outer value
if (list.get(j).compareTo(list.get(i)) < 0) {
// store the index of the smaller value
smallest = j;
// set the boolean flag to true so the sort will happen
needsSorting = true;
}
}
// if the list needs sorting
if (needsSorting) {
// get the value of the outer loop, store in generic variable
T temp = list.get(i);
// replace value of outer loop with value at the smallest index
list.set(i, list.get(smallest));
// replace value at what was smallest index with the value that
// was at the index of the outer loop
list.set(smallest, temp);
needsSorting = false;
}
}
}
}
The problem may be occurring at this line,
if (list.get(j).compareTo(list.get(i)) < 0)
Instead of list.get(i), it should be list.get(smallest)
Also, you're not updating smallest, when you should be doing so in each iteration of the outer for loop. Add this line of code right after for (int i = 0; i < list.size() - 1; i++)
smallest = i;
DaneBrick set me in the right direction. I needed to set the smallest variable to be equal to i, the counter for the outer loop, for each iteration of the outer loop. Here is the corrected portion of the code:
for (int i = 0; i < list.size() - 1; i++) {
// inner for searches for a smaller value than the front of list
//*** NEW PORTION, DIDN'T HAVE THIS BEFORE ***//
smallest = i;
for (int j = i + 1; j < list.size(); j++) {
// if the inner value is less than the outer value
if (list.get(j).compareTo(list.get(smallest)) < 0) {
// store the index of the smaller value
smallest = j;
// set the boolean flag to true so the sort will happen
needsSorting = true;
}
}

Categories