Comparing two rows in a single 2D array - java

I am trying to compare two rows that are in different order from a 2D array, and store elements that are the same from both rows. Here's an example of what I have produced:
String[] row1 = new String[10];
String[] row2 = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
for (int i = 0; i < fruit.length; i++ ) {
for (int j = 0; j < fruit[i].length; j++){
if(fruit[0][j].equals(fruit[1][j])) {
row1[j] = fruit[0][j];
row2[j] = fruit[1][j];
System.out.println("Match found");
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1");
System.out.println(Arrays.deepToString(row1));
System.out.println("row2");
System.out.println(Arrays.deepToString(row2));
I want the row1[] and row2[] to store the elements that are the same (which is kiwi in this example). However, the problem is .equals function only detects matching patterns. The example above only prints out nulls from row1 and row2.
It should really print out:
row1
[kiwi]
row2
[kiwi]
Note: I don't want to declare... String check = "kiwi"; because the user can enter anything in the 2D array.
Any suggestions? I feel I am getting close. I saw a similar example of someone using .equals and that worked, but it was only for single arrays.

The limits of your for-loops have been messed up, as well as the array elements that you accessed for comparison. I guess you wanted something like this...
import java.util.Arrays;
public class RowCompare
{
public static void main(String[] args)
{
String[] row1 = new String[10];
String[] row2 = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
for (int i = 0; i < fruit[0].length; i++ ) {
for (int j = 0; j < fruit[1].length; j++){
if(fruit[0][i].equals(fruit[1][j])) {
row1[i] = fruit[0][i];
row2[j] = fruit[1][j];
System.out.println("Match found");
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1");
System.out.println(Arrays.deepToString(row1));
System.out.println("row2");
System.out.println(Arrays.deepToString(row2));
}
}
But you should probably describe what you want to do with the results. These fixed-size result arrays (String[10]) look dubious, and the currently sketched code can not easily be generalized for MORE than 2 rows. There is probably a MUCH more elegant solution using Sets and Lists ....

You're logic is slightly wrong in your loop.
If you look you are comparing
fruit[0][0].equals(fruit[1][0])
then
fruit[0][1].equals(fruit[1][1])
change if statement to
if(fruit[0][i].equals(fruit[1][j])) {

Your solution is very uneffective since you don't take advantage of the optimization algorythms like hashing:
You should use a HashSet or a HashMap to find fastly if an element is contained.
In addition collections have ready methods like retainAll() to keep only the existing elements (HashSet implements Collection so it's a good candidate for your needs)
retainAll: Retains only the elements in this collection that are contained in the
specified collection (optional operation)
HashSet row1 = new HashSet();
row1.add("Kiwi");
...
HashSet row2 = new HashSet();
row2.add...
System.out.println( row1.retainAll(row2) );

It is less confusing to put the sub-arrays into temporary (1D) arrays: row1Temp and row2Temp.
import java.util.Arrays;
/**
<P>{#code java DoubleArrayXmpl}</P>
**/
public class DoubleArrayXmpl {
public static final void main(String[] igno_red) {
String[] row1Output = new String[10];
String[] row2Output = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
row1Output[i] = row1Temp[i];
row2Output[j] = row2Temp[j];
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1Output");
System.out.println(Arrays.deepToString(row1Output));
System.out.println("row2Output");
System.out.println(Arrays.deepToString(row2Output));
}
}
Output:
[C:\java_code\]java DoubleArrayXmpl
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
row1Output
[null, null, kiwi, null, null, null, null, null, null, null]
row2Output
[kiwi, null, null, null, null, null, null, null, null, null]
I don't know your requirements, but It's a little odd to put these duplicate values into two different arrays, let alone leaving so many values null. How about using an ArrayList to store a single copy of the matched fruit?
import java.util.Arrays;
/**
<P>{#code java DoubleArrayXmpl}</P>
**/
public class DoubleArrayXmpl {
public static final void main(String[] igno_red) {
ArrayList<String> alMatches = new ArrayList<String>(3);
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
alMatches.add(row1Temp[i]);
}else{
System.out.println("Not found");
}
}
}
System.out.println("All matched fruits:");
for(String s : alMatches) {
System.out.println(s);
}
}
}
Output:
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
All matched fruits:
kiwi
Or even better, just store the indexes of the matches:
import java.util.Arrays;
import java.util.ArrayList;
/**
<P>{#code java DoubleArrayToMatchedIdxListXmpl}</P>
**/
public class DoubleArrayToMatchedIdxListXmpl {
public static final void main(String[] igno_red) {
ArrayList<Integer> alMatchIdxsInRow1 = new ArrayList<Integer>(3);
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
alMatchIdxsInRow1.add(i);
}else{
System.out.println("Not found");
}
}
}
System.out.println("All matched fruits:");
for(int i : alMatchIdxsInRow1) {
System.out.println(fruit[0][i]);
}
}
}
Output:
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
All matched fruits:
kiwi

Related

Encoding a String Array

EDIT : [Schoolwork Assignment]
So, I want to encode, with only 0 and 1, words.
0 = word not present
1 = word present
My dictionary correspond to :
String[] dictionary = {"Hello", "I", "am", "Lukas", "and", "Jonas", "play", "football"};
For example : If I encode these words...
String[] listOfWords = {"Hello", "play" "football"};
I must have the following array :
int[] wordsEncode = {1,0,0,0,0,0,1,1};
You can see that "Hello" is present, "I" "am" "Lukas" "and" "Jonas" are not present. Finally, "play" and "football" are present.
We must preserve the order of dictionary and that is my problem in my code.
I don't really know how to fix that problem (using a second for loop ?) ?
I think wordEncode[i] is my error, but how to fix that ?
Here is my code :
class Dictionary {
/**
* Array words Dictionary
*/
String[] dictionary;
/**
* Maximum of words MAX_WORDS
*/
final int MAX_WORDS = 50;
/**
* Number of words in the dictionary
*/
int numberWordsDictionary;
/**
* Constructor
*/
Dictionary() {
dictionary = new String[MAX_WORDS];
numberWordsDictionary = 0;
}
int[] encoder(String[] listOfWords) {
int[] wordsEncode = new int[numberWordsDictionary];
StringBuilder builder = new StringBuilder();
for(String word : dictionary) {
builder.append(word);
}
String dictionaryString = builder.toString();
for(int i = 0; i < listOfWords.length; i++) {
if(dictionaryString.contains(listOfWords[i])) {
wordsEncode[i] = 1;
} else {
wordsEncode[i] = 0;
}
}
return wordsEncode;
}
}
Sorry about indentation (not same as my Java IDE) :(
Thanks !
Using two-level nested loops, you should check each element of dictionary[] whether it is there in listOfWords[] and if yes, update the value at the corresponding index in wordsEncode[] to 1.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String[] dictionary = { "Hello", "I", "am", "Lukas", "and", "Jonas", "play", "football" };
String[] listOfWords = { "Hello", "play", "football" };
int[] wordsEncode = new int[dictionary.length];
for (int i = 0; i < dictionary.length; i++) {
boolean found = false;
for (String s : listOfWords) {
if (s.equals(dictionary[i])) {
found = true;
break;
}
}
if (found) {
wordsEncode[i] = 1;
}
}
// Display the result
System.out.println(Arrays.toString(wordsEncode));
}
}
Output:
[1, 0, 0, 0, 0, 0, 1, 1]
Loop your input words. For each input word, see if your list of target words contains that particular word. If so, add a 1 to your results list. If not, add zero.
I use the more convenient Collections, but you could do the same approach with arrays.
List< String > input = List.of( "Hello", "I", "am", "Lukas", "and", "Jonas", "play", "football" ) ;
List< String > targets = List.of( "Hello", "play" "football" ) ;
List< Integers > hits = new ArrayList<>() ;
for( String s : input )
{
int i = targets.contains( s ) ? 1 : 0 ;
hits.add( i ) ;
}
What you did here is iterate through dictionary array and added the words to a StringBuilder to check if a certain word you got in the listOfWords array is in the StringBuilder. But there a better solution to this you can just make a nested loop that compares every element of listOfWords array and dictionary array and if it found a match it sets the encode array value at the index of the second loop to 1:
int[] encoder(String[] listOfWords) {
int[] wordsEncode = new int[numberWordsDictionary];
for (int i = 0; i < listOfWords.length; i++) {
for (int j = 0; j < numberWordsDictionary; j++) {
if (listOfWords[i].equals(dictionary[j])) {
wordsEncode[j] = 1;
break;
}
}
}
return wordsEncode;
}
/* This approach is wrong, the combined string could catch words that are
part of the ending of one word and part of the beginning of another but
not actually a word in the dictionary. For instance, if you had
"arch" and "attach" in your dictionary, testing for "chat" would return true
*/
/*
StringBuilder builder = new StringBuilder();
for(String word : dictionary) {
builder.append(word);
}
String dictionaryString = builder.toString();
*/
for(int i = 0; i < listOfWords.length; i++) {
boolean found = false;
for (int j = 0; j < dictionary.length; j++) {
if (dictionary[j].equalslistOfWords[i]) {
found = true;
}
}
if (found) {
wordsEncode[i] = 1;
} else {
wordsEncode[i] = 0;
}
// you can also do wordsEncode[i] = found ? 1 : 0;
}
return wordsEncode;
}

How to create a shorter array based on another?

I have an array like this (source)
[Maria Carolina, Luisa Joana, Lara Silva, Catarina Patricio, Paula Castro, fim, null, null, null]
and I want an array like that (destination)
[Maria Carolina, Luisa Joana, Lara Silva, Catarina Patricio, Paula Castro]
In the following code i is the number of names.
My code is:
String[] nomeCompleto = new String[10];
String[] nomes = new String[10-i];
if(i < 10) {
nomes[i] = nomeCompleto[i];
}
System.out.println(Arrays.toString(nomes));
return;
What am I doing wrong?
Edit: The question presents a source code fragment based on array indices, hence my original answer:
Use the Arrays class to do this for you.
String[] names = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
String[] truncated = java.util.Arrays.copyOf(names, names.length-4); // remove the last 4 names
System.out.println(java.util.Arrays.toString(truncated));
Try it online here.
Edit: Since people (not the OP) weren't too happy with that, I added: Or, to match only names of the form Firstname Lastname, use a regex:
String[] input = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
List<String> namesList = new ArrayList<>();
for(String name : input) {
if(name != null && name.matches("^[A-Z][A-z]+ [A-Z][a-z]+$"))
namesList.add(name);
}
String[] namesArray = namesList.toArray(new String[0]);
System.out.println(Arrays.toString(namesArray));
Try it online here.
Edit: Finally, since Dukeling commented on fim meaning end in Portuguese, a better solution might be:
Use a loop to find the first occurrence of fim and then truncate the array accordingly (as in the first code snippet in my answer).
String[] names = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
int newLength = names.length;
for(int i = 0; i < names.length; i++) {
if("fim".equals(names[i])) {
newLength = i;
break;
}
}
String[] truncated = java.util.Arrays.copyOf(names, newLength);
System.out.println(java.util.Arrays.toString(truncated));
Try it online here.
As per the Question's understanding Problem statement is as follows
Given a master array of String we need to return another array which contains the elements of master with null elements and element with value "fim" removed.
There can be null elements in between and not neccessary in the last and same for the element "fim"
Basic Algorithm
iterate master array
count the number of null & fim elements, create copy array of size =
master array size - null elements count
Check if the element is null if not null then add to copy array
public String[] removeNullNFimElementsFromArray(String[] master) {
int nullNFimCount = 0;
int masterSize = master.length;
for(int i = 0; i < masterSize; i++) {
if(master[i] == null || "fim".equals(master[i])) {
nullNFimCount++;
}
}
int copySize = masterSize - nullNFimCount;
String[] copyArray = new String[copySize];
for(int i = 0, j = 0; i < masterSize; i++) {
if(master[i] != null && !"fim".equals(master[i])) {
copyArray[j] = master[i];
j++;
}
}
return copyArray;
}

Remove duplicates in 2d array

I want to remove duplicate row in a 2d array . i tried the below code .but it is not working . please help me .
Input :
1,ram,mech
1,ram,mech
2,gopi,csc
2.gopi,civil
output should be :
1,ram,mech
2,gopi,csc
2.gopi,civil
Code :
package employee_dup;
import java.util.*;
public class Employee_dup {
public static void main(String[] args)
{
boolean Switch = true;
System.out.println("Name ID Dept ");
String[][] employee_t = {{"1","ram","Mech"},{"1","siva","Mech"},{"1","gopi","Mech"},{"4","jenkat","Mech"},{"5","linda","Mech"},{"1","velu","Mech"}};
int g = employee_t[0].length;
String[][] array2 = new String[10][g];
int rows = employee_t.length;
Arrays.sort(employee_t, new sort(0));
for(int i=0;i<employee_t.length;i++){
for(int j=0;j<employee_t[0].length;j++){
System.out.print(employee_t[i][j]+" ");
}
System.out.println();
}
List<String[]> l = new ArrayList<String[]>(Arrays.asList(employee_t));
for(int k = 0 ;k < employee_t.length-1;k++)
{
if(employee_t[k][0] == employee_t[k+1][0])
{
System.out.println("same value is present");
l.remove(1);
array2 = l.toArray(new String[][]{});
}
}
System.out.println("Name ID Dept ");
for(int i=0;i<array2.length;i++){
for(int j=0;j<array2[0].length;j++){
System.out.print(array2[i][j]+" ");
}
System.out.println();
}
}
}
class sort implements Comparator {
int j;
sort(int columnToSort) {
this.j = columnToSort;
}
//overriding compare method
public int compare(Object o1, Object o2) {
String[] row1 = (String[]) o1;
String[] row2 = (String[]) o2;
//compare the columns to sort
return row1[j].compareTo(row2[j]);
}
}
First I sorted the array based on column one ,then tried to remove duplicates by checking the first column elements and seconds column elements but it is not removing the required column but remove other columns.
You may give this solution a try:
public static void main(String[] args) {
String[][] employee_t = {
{"1","ram","Mech"},
{"1","ram","Mech"},
{"1","siva","Mech"},
{"1","siva","Mech"},
{"1","gopi","Mech"},
{"1","gopi","Mech"} };
System.out.println("ID Name Dept");
Arrays.stream(employee_t)
.map(Arrays::asList)
.distinct()
.forEach(row -> System.out.printf("%-3s%-7s%s\n", row.get(0), row.get(1), row.get(2)));
}
Output
ID Name Dept
1 ram Mech
1 siva Mech
1 gopi Mech
How it works: comparing arrays does rely on instance equality and not on comparing contained elements by equals. Hence converting each row of your 2D array into a List will enable you to compare lists, which takes equals of the elements contained into account.
The Java Stream API does provide a method distinct which relies on equals and will remove all duplicates for you.
Based on your code. Maybe it is not the BEST solution but it works.
public static void main(String[] args) {
System.out.println("Name ID Dept ");
// I added duplicated rows
String[][] inputArray = {
{ "1", "ram", "Mech" },
{ "1", "siva", "Mech" },
{ "1", "gopi", "Mech" },
{ "1", "gopi", "Mech" },
{ "4", "jenkat", "Mech" },
{ "5", "linda", "Mech" },
{ "1", "velu", "Mech" },
{ "1", "velu", "Mech" }
};
// I will add all rows in a Set as it doesn't store duplicate values
Set<String> solutionSet = new LinkedHashSet<String>();
// I get all rows, create a string and insert into Set
for (int i = 0 ; i < inputArray.length ; i++) {
String input = inputArray[i][0]+","+inputArray[i][1]+","+inputArray[i][2];
solutionSet.add(input);
}
// You know the final size of the output array
String[][] outputArray = new String[solutionSet.size()][3];
// I get the results without duplicated values and reconvert it to your format
int position = 0;
for(String solution : solutionSet) {
String[] solutionArray = solution.split(",");
outputArray[position][0] = solutionArray[0];
outputArray[position][1] = solutionArray[1];
outputArray[position][2] = solutionArray[2];
position++;
}
System.out.println("Name ID Dept ");
for (int i = 0; i < outputArray.length; i++) {
for (int j = 0; j < outputArray[0].length; j++) {
System.out.print(outputArray[i][j] + " ");
}
System.out.println();
}
}
I have posted what I think is a readable and easy to maintain solution.
I decided to use distinct from Stream which is part of Java 8
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream. - https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#distinct--
Main.class
class Main {
public static void main(String[] args)
{
//Create a list of Employee objects
List<Employee> employeeList = new ArrayList<Employee>();
Employee e1 = new Employee(1, "ram", "mech");
Employee e2 = new Employee(1, "ram", "mech");
Employee e3 = new Employee(2, "gopi", "csc");
Employee e4 = new Employee(2, "gopi", "civil");
employeeList.add(e1);
employeeList.add(e2);
employeeList.add(e3);
employeeList.add(e4);
System.out.println("Before removing duplicates");
employeeList.stream().forEach(System.out::println);
//This is where all the magic happens.
employeeList = employeeList.stream().distinct().collect(Collectors.toList());
System.out.println("\nAfter removing duplicates");
employeeList.stream().forEach(System.out::println);
}
}
Output:
Before removing duplicates
Employee [valA=1, valB=ram, valC=mech]
Employee [valA=1, valB=ram, valC=mech]
Employee [valA=2, valB=gopi, valC=csc]
Employee [valA=2, valB=gopi, valC=civil]
After removing duplicates
Employee [valA=1, valB=ram, valC=mech]
Employee [valA=2, valB=gopi, valC=csc]
Employee [valA=2, valB=gopi, valC=civil]
Employee.class
//This is just a regular POJO class.
class Employee {
int valA;
String valB, valC;
public Employee(int valA, String valB, String valC){
this.valA = valA;
this.valB = valB;
this.valC = valC;
}
public Employee(Employee e) {
this.valA = e.valA;
this.valB = e.valB;
this.valC = e.valC;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + valA;
result = prime * result + ((valB == null) ? 0 : valB.hashCode());
result = prime * result + ((valC == null) ? 0 : valC.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Employee && ((Employee)obj).hashCode() == this.hashCode()){
return true;
}
return false;
}
#Override
public String toString() {
return "Employee [valA=" + valA + ", valB=" + valB + ", valC=" + valC + "]";
}
}
Pre Java - 8 solution. May not be the best way. But a quick solution which works..
String[][] records = {
{"1","ram","Mech"},
{"1","ram","Mech"},
{"1","gopi","csc"},
{"1","gopi","civil"} };
List<String[]> distinctRecordsList = new ArrayList<String[]>();
for(String[] record : records){
if(distinctRecordsList.size()>0){
boolean sameValue = false;
for(String[] distinctRecord : distinctRecordsList){
int distinctRecordFields = distinctRecord.length;
if(record.length==distinctRecordFields){
for(int k=0;k<distinctRecordFields;k++){
sameValue = record[k].equalsIgnoreCase(distinctRecord[k]);
if(!sameValue)
break;
}
}else
throw new Exception("Can't compare the records");
}
if(!sameValue)
distinctRecordsList.add(record);
}else if(distinctRecordsList.size()==0)
distinctRecordsList.add(record);
}
Object[] distRecObjects = distinctRecordsList.toArray();
String[][] distinctRecordsArray = new String[distRecObjects.length][];
int i=0;
for(Object distRecObject : distRecObjects){
distinctRecordsArray[i] = (String[]) distRecObject;
i++;
}
Contrary to some other answers I will try to explain what went wrong in your own code and how to fix it within your code (I agree very much with kkflf that an Employee class would be a huge benefit: it’s more object-oriented and it will help structure the code and give better overview of it).
The issues I see in your code are:
You are not removing the correct element when you detect a duplicate, but always the element at index 1 (the second element since indices count from 0). This isn’t trivial, though, because indices shift as you remove elements. The trick is to iterate backward so only indices that you are finished with shift when you remove an element.
You are using == to compare the first element of the subarrays you are comparing. If you wanted to compare just the first element, you should use equals() for comparison. However, I believe you want to compare the entire row so 2,gopi,csc and 2.gopi,civil are recognized as different and both preserved. Arrays.equals() can do the job.
You need to create array2 only after the loop. As your code stands, if no duplicates are detected, arrays2 is never created.
So your loop becomes:
for (int k = employee_t.length - 1; k >= 1; k--)
{
if (Arrays.equals(employee_t[k], employee_t[k - 1]))
{
System.out.println("same value is present");
l.remove(k);
}
}
array2 = l.toArray(new String[][]{});
This gives you the output you asked for.
Further tips:
Your comparator only compares one field in the inner arrays, which is not enough to guarantee that identical rows come right after each other in the sorted array. You should compare all elements, and also require that the inner arrays have the same length.
Use generics: class Sort extends Comparator<String[]>, and you won’t need the casts in compare()
According to Java naming conventions it should be class EmployeeDup, boolean doSwitch (since switch is a reserved word) and class Sort.
You are not using the variables Switch and rows; delete them.
I have wrote a solution for me. This may not be the best but it works.
public static String[][] removeDuplicate(String[][] matrix) {
String[][] newMatrix = new String[matrix.length][matrix[0].length];
int newMatrixRow = 1;
for (int i = 0; i < matrix[0].length; i++)
newMatrix[0][i] = matrix[0][i];
for (int j = 1; j < matrix.length; j++) {
List<Boolean> list = new ArrayList<>();
for (int i = 0; newMatrix[i][0] != null; i++) {
boolean same = true;
for (int col = 2; col < matrix[j].length; col++) {
if (!newMatrix[i][col].equals(matrix[j][col])) {
same = false;
break;
}
}
list.add(same);
}
if (!list.contains(true)) {
for (int i = 0; i < matrix[j].length; i++) {
newMatrix[newMatrixRow][i] = matrix[j][i];
}
newMatrixRow++;
}
}
int i;
for(i = 0; newMatrix[i][0] != null; i++);
String finalMatrix[][] = new String[i][newMatrix[0].length];
for (i = 0; i < finalMatrix.length; i++) {
for (int j = 0; j < finalMatrix[i].length; j++)
finalMatrix[i][j] = newMatrix[i][j];
}
return finalMatrix;
}
This method will return a matrix without any duplicate rows.

Removing a String from a ragged 2D String array and shortening the array in the process

My professor gave out a review question for our midterm this week that I'm confused on:
Write a method that is given a two-dimensional (ragged) array of
String objects and returns a two-dimensional (ragged) array of String
objects where all the null entries have been removed. For example,
if the original array has the data (NULL represents a null
reference):
{"John", null, "Mary", "George", null},{null, "Pete", "Rick"},{null, null, null}};
the result generated by your method will be a two-dimensional
array with three rows.
{"John", "Mary", "George"},{"Pete", "Rick"},{}}; // last row will be empty
The code I have is:
public static String[][] removeNull2D(String[][] ragged) {
int counter = 0;
int nullCounter = 0;
String[][] array; // isn't initialized
// doesn't work I tested in debugger, need a way to shorten each row by the amount of null values it has
for (int i = 0; i < ragged.length; i++) {
for (int j = 0; j < ragged[i].length; j++) {
if (ragged[i][j] == null) {
nullCounter++;
for (j = 0; j < ragged[i].length; j++) {
array = new String[ragged.length][ragged[i].length - nullCounter];
}
}
}
}
// based off 1D array approach
for (int i = 0; i < ragged.length; i++) {
for (int j = 0; j < ragged[i].length; j++) {
if (ragged[i][j] != null) {
array[i][counter++] = ragged[i][j];
}
}
}
return ragged;
}
I understand I need to count the amount of null values in each row and subtract that from the total length of each row for the String array "array" (bad name I know). I thought maybe if I made a method for a 1D array, it would help me understand the logic a little better:
public static String[] removeNull1D(String[] a) {
String[] array = new String[a.length - 1];
int counter = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != null) {
array[counter++] = a[i];
}
}
a = array;
return array;
}
Still confused how the logic applies to the 2D ragged array method, any clarification would be appreciated! Also, I don't believe I can import anything (are not supposed to at least), and once again this is just a review question, so I'm not stressing about getting an answer, just trying to understand the logic behind it.
You could try it like this:
public static void main(String[] args) {
String[][] ragged = { { "John", null, "Mary", "George", null }, { null, "Pete", "Rick" }, { null, null, null } };
String[][] cleaned = new String[ragged.length][];
for (int i = 0; i < ragged.length; i++) {
cleaned[i] = clean(ragged[i]); // Apply clean method to each sub array.
}
System.out.println(Arrays.deepToString(cleaned));
}
private static String[] clean(String[] dirty) {
int nonNullCount = 0;
for (String string : dirty) {
if (string != null) {
nonNullCount++; // Count non-null Strings.
}
}
String[] clean = new String[nonNullCount]; // Create array for non-null Strings.
int cleanIndex = 0;
for (String string : dirty) {
if (string != null) {
clean[cleanIndex] = string; // Insert only non-null String at index.
cleanIndex++; // Only then update index.
}
}
return clean;
}
Seems a little bit inelegant to me, but at the moment I can't think of a way to prevent the double loop in clean(String[] dirty)
Nevertheless, it outputs [[John, Mary, George], [Pete, Rick], []] as desired.
Edit: Updated some commentary.

find duplicate words in java array and return array with unique duplicate words - use method

I am new to java, and am confused with the problem.
This is what I came up so far.
I am still working on it, if I come up with any progress, I'll post it here.
public class charArray {
public static void main(String[] args) {
String[] strArray = new String[] {"apple", "ball", "cat", "apple", "ball", "apple"};
//output should be ["apple", "ball"]
checkDuplicate(strArray);
}
public static String[] checkDuplicate(String[] strArray){
String[] newArray = new String[]{};
for(int i = 0; i < strArray.length; i++){
for(int j = 0; j < i; j++){
if (strArray[i].equals(srtArray[j])){
newArray = strArray[i];
}
}
}
return newArray[];
}
}
New progress:
Ok, my mediocre head has gone this far: (and the solution works)
It prints out the unique array of Duplicate elements.
But now I need to implement the same code, by calling a method.
Any help is appreciated.
import java.util.*;
public class setChar {
public static void main(String[] args) {
String[] strArray = new String[] {"apple", "ball", "cat", "apple", "ball", "apple"};
Set set = new HashSet();
Set uniqueSet = new HashSet();
for(int i = 0; i < strArray.length ; i++ ){
boolean b = set.add(strArray[i]);
if(b == false){
uniqueSet.add(strArray[i]);
}
}
Iterator it = uniqueSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
The output is:
ball
apple
Finally implemented with method, with proper return type.
Please let me know, if this can be further optimized.
Thank all for you suggestions. Here is the working code:
public class retUnique {
public static void main(String[] args) {
String[] strArray = new String[] {"apple", "ball", "cat", "apple", "ball", "apple"};
System.out.println(printUnique(strArray));
}
public static Set<String> printUnique(String[] strArray){
Set<String> set = new HashSet<String>();
Set<String> uniqueSet = new HashSet<String>();
for(int i = 0; i < strArray.length ; i++ ){
boolean b = set.add(strArray[i]);
if(b == false){
uniqueSet.add(strArray[i]);
}
}
return(uniqueSet);
}
}
One easy option is to use a Set like container instead of an array. It will automatically ensure that only unique values are present.
You can look at examples of TreeSet and HashSet.
Something like this should work I believe. Been a while since I coded in Java so if anyone wants to make edits, please do.
public String[] returnDups(String[] strArray) {
Set<String> set = new HashSet<String>(strArray);
return set.toArray(new String[0]);
}
But what everyone has been suggesting is the correct idea. Sets make it really easy to remove duplicates so you should utilize them. Let's not reinvent the wheel.
To detect dupplicates, if that is your question, add all elememts of the array to a Set, if set.add() returns false, then it is a dupplicate, so you can add this elemen to your result list of dupplictes.
Or if your question is meaning to return the values without duplicates, then you can retirnthe set, or convert the set to list before returning.

Categories