Reputation: 371
I have a class named Data; i have a list with some data and a function that filters this list with properties of data class
if a,b,c filter words are not empty => data object must have these 3
if a,b are not empty => data object must have these 2
if a,c are not empty => data object must have these 2
if b,c are not empty => data object must have these 2
if a is not empty => data object must have this
if b is not empty => data object must have this
if c is not empty => data object must have this
as you can see i wrote a code that fulfills its job but i did not like my algorithm, so can you suggest me more smart algorithm because if field count of class increase i need to wrote new ifs. (i am using java but i will not add java tag maybe there is a good pseudo code but javas functions are accepted too )
public class Data {
private String a;
private String b;
private String c;
private String getA() {
return a;
}
private String getB() {
return b;
}
private String getC() {
return c;
}
private List<Data> filterData(List<Data> datas, String a, String b, String c) {
List<Data> result = new ArrayList<>();
for (Data data : datas) {
if (a != null && data.getA().equals(a) && b != null && data.getB().equals(b) && c != null && data.getC().equals(c)) {
result.add(data);
} else if (a != null && data.getA().equals(a) && b != null && data.getB().equals(b)) {
result.add(data);
} else if (a != null && data.getA().equals(a) && c != null && data.getC().equals(c)) {
result.add(data);
} else if (b != null && data.getB().equals(b) && c != null && data.getC().equals(c)) {
result.add(data);
} else if (a != null && data.getA().equals(a)) {
result.add(data);
} else if (b != null && data.getB().equals(b)) {
result.add(data);
} else if (c != null && data.getC().equals(c)) {
result.add(data);
} else {
return null;
}
}
return result;
}
}
assume that you have cars list and Car class has color (a), model year (b), fuel type (c) assume that they are string not enum or you dont need to compare model year from its range
Upvotes: 0
Views: 80
Reputation: 82929
You can drastically reduce the number of if
checks if you transform your condition. Currently, your condition (split up over 7 if
checks), looks roughly like this:
(a & b & c) | (b & c) | (a & c) | (a & b) | a | b | c
Where each of a
, b
and c
corresponds to x != null && data.getX().equals(x)
You can simplify this to just a & b & c
if you change those components to x == null || data.getX().equals(x)
, i.e. either the element is null, or it matches. You could also make this a separate method to make your code clearer. Also, you could replace the loop and if
checks with Stream.filter
private boolean matches(Object x, Object y) {
return x == null || x.equals(y);
}
private List<Data> filterData(List<Data> datas, String a, String b, String c) {
return datas.stream()
.filter(d -> matches(a, d.getA()))
.filter(d -> matches(b, d.getB()))
.filter(d -> matches(c, d.getC()))
.collect(Collectors.toList());
}
Note: 1) I changed data.getX().equals(x)
to x.equals(data.getX())
, as you already know that x
is != null
at this point, but getX()
might be null. Also, your final if
check, if all the filters are null
, added null
to the list, instead of data
. I assumed this was a mistake.
Upvotes: 1
Reputation: 46455
I believe that this is what you INTEND the combination to be. Though your description is ambiguous, and your existing code does not match it. (As @juvian said, your last 3 conditions as currently written cover the first 4.)
private List<Data> filterData(List<Data> datas, String a, String b, String c) {
List<Data> result = new ArrayList<>();
for (Data data : datas) {
if (! data.getA().equals(a == null ? data.getA() : a)) {
// Filtered out
}
else if (! data.getB().equals(b == null ? data.getB() : b)) {
// Filtered out
}
else if (! data.getC().equals(c == null ? data.getC() : c)) {
// Filtered out
}
else {
result.add(data);
}
}
return result;
}
Upvotes: 0
Reputation: 16068
Here is a more generalized approach: add the strings you want to filter to an array, then add the values from data in same order. Then we can compare them in a more generalized way by using the fact that they will have the same indexes.
List<String> filterBy = new List<String>{a, b, c};
for (Data data : datas) {
Boolean shouldAdd = true;
List<String> values = new List<String>{data.getA(), data.getB(), data.getC()};
for (Integer i = 0; i < filterBy.size(); i++) {
if (filterBy[i] != null && filterBy[i].equals(values[i]) == false) {
shouldAdd = false;
break;
}
}
if (shouldAdd) {
result.add(data);
}
}
Upvotes: 1