How to compare two different List of list? - java

Example of list:
List1 =[[1,2,3],[4,5],[6,7],[8,9,10]]
List2 =[[11,12],[13,14,15,16],[17,18,19],[20]]
I have two lists of list and want to compare list element in below fashion
1=>11, 2=>12,3=>No element present in List2
4=>13, 5->14,15->No element present in List1,16->No element present in List1
but the condition is List 2 can contain more element than list1. How i can compare two lists with each other?
I have checked online solutions and tried to iterate through for loop as well but none of them are fulfilled my requirement.
Size of list1 and list2 are equal and I have already added a check to start comparison only if size is equal.
I can iterate through both the lists with the help of for loop but struggling with the comparison.
for (int m = 0; m < List1 .size(); m++) {
for (int n = 0; n < List1 .get(m).size(); n++) {
System.out.println("List1" + m + "==>" + List1 .get(m).get(n));
}
System.out.println("========================================================");
}
for (int i = 0; i < List2.size(); i++) {
for (int k = 0; k < List2.get(i).size(); k++) {
System.out.println("========================================================");
System.out.println("List2" + i + "==>" + List2.get(i).get(k));
}
}

public static boolean isEqualsDeeply(List<List<Integer>> one, List<List<Integer>> two) {
one = one != null ? one : Collections.emptyList();
two = two != null ? two : Collections.emptyList();
if (one.size() != two.size())
return false;
Iterator<List<Integer>> it1 = one.iterator();
Iterator<List<Integer>> it2 = two.iterator();
while (it1.hasNext() && it2.hasNext()) {
List<Integer> subOne = it1.next();
List<Integer> subTwo = it2.next();
subOne = subOne != null ? subOne : Collections.emptyList();
subTwo = subTwo != null ? subTwo : Collections.emptyList();
if (subOne.size() != subTwo.size() || !subOne.equals(subTwo))
return false;
}
return true;
}
P.S.
It seems that for Integer standard equals works fine as well:
public static boolean isEqualsDeeply(List<List<Integer>> one, List<List<Integer>> two) {
one = one != null ? one : Collections.emptyList();
two = two != null ? two : Collections.emptyList();
return one.equals(two);
}

You can use Math.max(int n, int m) to compare the list sizes and get the longest one for your nested for loop. Example:
public static void main(String[] args) {
List<List<Integer>> list1 = Arrays.asList(
Arrays.asList(1,2,3),
Arrays.asList(4,5),
Arrays.asList(6,7),
Arrays.asList(8,9,10));
List<List<Integer>> list2 = Arrays.asList(
Arrays.asList(11,12),
Arrays.asList(13,14,15,16),
Arrays.asList(17,18,19),
Arrays.asList(20));
for(int i = 0; i <list2.size();i++){
int j = Math.max(list1.get(i).size(),list2.get(i).size());
for(int k = 0; k<j; k++){
System.out.print(k<list1.get(i).size()?list1.get(i).get(k) +" => ":"No element present in List1 => ");
System.out.print(k<list2.get(i).size()?list2.get(i).get(k) :"No element present in List2");
System.out.println("");
}
System.out.println("===============================");
}
}

Not sure if you're stuck on the java aspect of checking whether a list has another element remaining, of if you're stuck on the logic. If its the logic, here's some javascript code that gets the job done :
var list1 = [[1,2,3],[4,5],[6,7],[8,9,10]];
var list2 = [[11,12],[13,14,15,16],[17,18,19],[20],[21]];
function compareLists(l1,l2){
var i = 0;
var maxLength = Math.max(list1.length,list2.length);
for(i = 0; i< maxLength; i++){
var sl1 = list1[i], sl2 = list2[i];
compareSublists(sl1,sl2);
}
}
function compareSublists(sl1,sl2){
if(sl1 === undefined){
console.log(sl2 + " has no corresponding sublist in list 1");
}else if(sl2 === undefined){
console.log(sl1 + " has no corresponding sublist in lis 2");
}else{
var i = 0;
var maxLength = Math.max(sl1.length,sl2.length);
for(i=0; i<maxLength;i++){
var sl1e = sl1[i], sl2e = sl2[i];
if(sl1e === undefined){
console.log(sl2e+" has no element in list 1");
}else if(sl2e === undefined){
console.log(sl1e+" has no element in list 2");
}else{
console.log(sl1e + " => " + sl2e);
}
}
}
}
compareLists(list1,list2);
Converting to java should not be too much of an issue; however I haven't touched java in years, so I can't help you out there, apologies.

Related

Loop through multiple arraylists and get elements

public static void main(String[] args)
{
loadDependencies ld = new loadDependencies();
List<String> ls = ld.loadDependenciesFromPom();
getAvailableHigherVersions ah = new getAvailableHigherVersions();
List<List<String>> vl = ah.versionListOnly();
String previousVersion=null;
for ( int a=0; a<vl.size();a++) {
List<String> tmp = vl.get(a);
for(int i=0; i<ls.size();i++){
String firstE = ls.get(i);
for(int j=0;j<tmp.size();j++) {
if (i==0 && j==0){
//xu.versionUpdate(previousVersion, tmp.get(j));
//String previousVersiontt = ls.get(i);
System.out.println(firstE + "----" + tmp.get(j));
}
/*xu.versionUpdate(previousVersion, tmp.get(j));
previousVersion=tmp.get(j);*/
//System.out.println(previousVersion+"-"+tmp.get(j));
// previousVersion = tmp.get(j);
}
}
}
}
"ls" is a String list. It contains like this
[1,4,5,7]
"vl"is a List of string list. It contains like this
[[1.5,1.6,1.7],[4.1,4.2,4.3],[5.1,5.2],[7.1,7.4]]
what I need to do is first take the 1st element of ls list
1
then i need to get the first element in the vl list
[1.5,1.6,1.7]
then output should be
[1,1.5]
then the next output would be
[1.5,1.6]
likewise iterate through the array.
Then next take the 2nd element of ls
4
then it should go like 4,4.1 then 4.1,4.2 likewise until the ls is empty.
I tried above code but some times it iterate multiple times. Any hint to fix this issue?
So if I understood well, you want something like this:
for (int a = 0; a < ls.size(); a++)
{
// Get first element
String firstE = ls.get(a);
// Get corresponding vl elements
List<String> vls = vl.get(a);
// Now print the elements
// The first element of vl should be preceeded by the corresponding element in ls
// The others by the predecessor in the same array
for (int b = 0; b < vls.size(); b++)
{
System.out.print("[");
if (b == 0)
System.out.print(firstE);
else
System.out.print(vls.get(b - 1));
System.out.println(", " + vls.get(b) + "]");
}
}
for(int i=0;i<ls.size();i++){
List<String> tmp = vl.get(i);
System.out.println(ls.get(i)+" "+temp.get(0));
for(int j=1;j<tem.size()-1;j++){
System.out.println(temp.get(j)+" "+temp.get(j+1));
}
}
for ( int a=0; a<vl.size();a++) {
List<String> tmp = vl.get(a);
String firstE = ls.get(a);
for (int j = 0; j < tmp.size(); j++) {
if (j == 0) {
//xu.versionUpdate(previousVersion, tmp.get(j));
//String previousVersiontt = ls.get(i);
System.out.println(firstE + "----" + tmp.get(j));
}
/*xu.versionUpdate(previousVersion, tmp.get(j));
previousVersion=tmp.get(j);*/
//System.out.println(previousVersion+"-"+tmp.get(j));
// previousVersion = tmp.get(j);
}
}
}

I have an array and I want to check if all the values from array are equal to what I want using edittext

Here is an example of my array
List<Integer> sampleList = new ArrayList<>();
all values inside this array are:
sampleList = [1,2,3,4,5,6]
Basically I'm using for to loop each values from this array
for (int i = 0; i < sampleList.size(); i++) {
int to = sampleList.get(i);
if (norooms == to) { //norooms = 1
//display a toast
}
}
I want to check if position 0-5 are all equal to 1 but I cant achieve it. Any help
You can try something like this.
int editTextValue = 3; // Your edit text value
boolean isEqual = true;//Flag to check if all the values are equal or not.
for (int i=0; i<sampleList.size(); i++){
if (sampleList.get(i) != editTextValue){
isEqual = false;
break;
}
}
Then check the condition of isEqual after the loop is over and handle accordingly.
public Check {
int value;
int index;
boolean match;
// constructor, setters and getters
}
For about all the information you want:
public List<Check> checkValues(List<Integer> originalList, Integer testValue) {
List<Check> result = new ArrayList<>();
for ( int i = 0; i< originalList.size(); i++ ) {
result.add(new Check(i, originalList.get(i), originalList.get(i) == testValue);
}
return result;
}
This is 'a way' to do it. You'll have information on how many matches there were, which other values there were and on which index in your List they were found.
I'd use Java Streams, check out more on: Streams
Basically turns the list into a stream of elements and then you can process the data.
//To get only the elements equal to 1
sampleList.stream()
.filter((num) -> num == 1);
//to get a list of booleans whose value depends on the element being equal to 1.
List<Boolean> listBooleans = sampleList.stream()
.map((num) -> num == 1)
.collect(Collectors.toList())
filter uses a predicate to determine if the element matches a certain condition, in this case number == 1.
map transforms the stream of Integers into a Stream of booleans where the result is number == 1.
collect terminates the stream, with Collectors.toList transforms it into a List.
Hope this helps.
Arraylist<String> matchedValues = new Arraylist<>();
String editTextValue = edittext.getText();
String arrayValue;
boolean isEqual ;
boolean isEveryElementPresent = false;
for (int i = 0 ; i < sampleList.size() ; i++){
arrayValue = sampleList.get(i);
if(arrayValue.equals(editTextValue)){
isEqual = true;
matchedValues.add(arrayValue);
}else{
isEqual =false;
}
}
if(matchedValues.size() == sampleList.size()){
isEveryElementPresent = true;
}

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.

Checking list of strings entirely contained in other list of strings

I wrote this piece of code to check wheter a list of strings is entirely contained in another one and in that case delete the list.
public static void main(String[] args) {
LinkedList<String> l1 = new LinkedList<String>();
LinkedList<String> l2 = new LinkedList<String>();
l1.add("Cc");
l1.add("Dd");
l2.add("Cc");
l2.add("Dd");
l2.add("Ee");
LinkedList<LinkedList<String>> l = new LinkedList<LinkedList<String>>();
l.add(l1);
l.add(l2);
System.out.println("OUTPUT: " + filterSublist(l));
}
static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) {
List<LinkedList<String>> uniq = new LinkedList<LinkedList<String>>(l);
l.forEach(elem -> uniq.removeIf(x -> !x.equals(elem) && elem.contains(x)));
return uniq;
}
The function filterSubList should return a list of list of strings which has no lists that are totally contained in other lists.
In the example we have:
List 1: "Cc, Dd"
List 2: "Cc, Dd, Ee"
Since list 1 is entirely contained in list 2, the function should return a list of lists that contains only list 2.
But when I run the program I got output which is a list that contains both:
OUTPUT: [[Cc, Dd], [Cc, Dd, Ee]]
This is wrong. Is there a mistake in the filterSubList function?
You are checking for one list (object) containing another list (object). A new list will be alloted differently in memory whenever a new object is created, Instead check for the objects inside with containsAll:
Try this instead:
static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) {
List<LinkedList<String>> uniq = new LinkedList<LinkedList<String>>(l);
l.forEach(elem -> uniq.removeIf(x -> !x.equals(elem) && elem.containsAll(x)));
return uniq;
}
In case Rene's raised some points relevant to the OP, here's an implementation that pretty much follows his lead, in a different way, though.
static List<LinkedList<String>> filterSublistAlternate(LinkedList<LinkedList<String>> l) {
boolean[] removed = new boolean[ l.size() ];
outer: for(int i=0; i< l.size() ; i++)
inner: for(int j=0; j< l.size() ; j++)
{
if( i != j )
if(l.get(j).containsAll(l.get(i)))
{
System.out.println(i+" and "+j);
if(l.get(i).size() == l.get(j).size())
if(removed[i] == removed[j] && !removed[i])
removed[i] = true;
else
continue outer;
else
{
removed[i] = true;
continue outer;
}
}
}
for(int i=removed.length-1; i>=0 ; i--)
if(removed[i])
l.remove(i);
return l;
}
I propose the solution below as it is:
more memory efficient as it doesn't duplicate the original list
more correct as it really checks for sublists (not just single element existence)
more correct as it removes duplicates from the result
Code:
static List<LinkedList<String>> filterSublist(LinkedList<LinkedList<String>> l) {
return l.stream()
.filter(x -> l.stream().noneMatch(elem -> !elem.equals(x) && Collections.indexOfSubList(elem, x) != -1))
.distinct()
.collect(Collectors.toList());
}

Comparing two lists and return an error if at least one entry is same

I have an object SalesType with fields SalesTypeId and SalesTypeCode.
I have two lists list1 and list2.
List1={(1,10),(2,20),(3,30)}
List2={(1,40),(2,50),(3,20)
I am trying to compare the SalesTypeCode code in the lists and if it is same then it has to exit the loop and return lists has same field.
Below is what I did but it is not returning what I am expecting.
What did I do wrong?
List<SalesType> list1 =service.getAllSalesTypeCodes(form.getReqSalesTypeGroup());
List<SalesType> list2 = service.getAllSalesTypeCodes(form.getSorSalesTypeGroup());
if (list1 != null || list2 != null) {
mainLoop:
for (int i = 0; i < list2.size(); i++) {
System.out.println("list2 " + list2.get(i).getSalesTypeCode());
for (int j = 0; j < list1.size(); j++) {
System.out.println("list1 " + list1.get(j).getSalesTypeCode());
if ((list2.get(i).getSalesTypeCode()).equals((list1.get(j).getSalesTypeCode()))) {
System.out.println("equals..:" + (list2.get(i).getSalesTypeCode()).equals((list1.get(j).getSalesTypeCode())));
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(ActionErrorConstants.MESSAGE_EXISTS_SALES_TYPE));
System.out.println("breaking the loop");
break mainLoop;
}
}
}
}
Override properly equals in the SalesType class (including HashCode) and then use
List#retainAll(...) method
or
List#.removeAll(... ) method

Categories