Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for 'distinctByColumn' method in DataTable #269

Merged
merged 2 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,50 @@

package io.github.selcukes.collections;

import lombok.experimental.UtilityClass;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

import static java.util.Optional.ofNullable;

@UtilityClass
public class DataComparator {
private final BiPredicate<Object, Object> valueComparator;
/**
* Constructs a DataComparator with the specified value comparator.
*
* @param valueComparator the value comparator to be used for comparing
* values.
*/
private DataComparator(BiPredicate<Object, Object> valueComparator) {
this.valueComparator = valueComparator;
}

/**
* Creates a new DataComparator with the default value comparator that uses
* the {@link Objects#equals} method.
*
* @return a new DataComparator instance.
*/
public static DataComparator create() {
return new DataComparator(Objects::equals);
}

/**
* Creates a new DataComparator with the specified value comparator.
*
* @param valueComparator the new value comparator to be used for comparing
* values.
* @return a new DataComparator instance with the updated
* value comparator.
*/
public static DataComparator create(BiPredicate<Object, Object> valueComparator) {
return new DataComparator(valueComparator);
}

/**
* Compares the data in two tables and returns a table of differences.
Expand All @@ -43,7 +73,7 @@ public class DataComparator {
* @return a table of differences between the expected and
* actual tables
*/
public static <K, V> DataTable<String, String> diff(
public <K, V> DataTable<String, String> diff(
final DataTable<K, V> expected, final DataTable<K, V> actual, final K foreignKey,
final List<K> ignoreColumns
) {
Expand Down Expand Up @@ -72,7 +102,7 @@ public static <K, V> DataTable<String, String> diff(
* @return a table of differences between the expected and actual
* tables
*/
public static <K, V> DataTable<String, String> diff(
public <K, V> DataTable<String, String> diff(
DataTable<K, V> expected, DataTable<K, V> actual, K foreignKey
) {
return diff(expected, actual, foreignKey, Collections.emptyList());
Expand All @@ -89,15 +119,15 @@ public static <K, V> DataTable<String, String> diff(
* @return a table of differences between the expected and
* actual rows
*/
public static <K, V> DataTable<String, String> diff(
public <K, V> DataTable<String, String> diff(
final Map<K, V> expected, final Map<K, V> actual, final List<K> ignoreColumns
) {
return expected.entrySet().stream()
.filter(entry -> !ignoreColumns.contains(entry.getKey()))
.map(entry -> {
var expectedValue = entry.getValue();
var actualValue = actual.get(entry.getKey());
String status = Objects.equals(expectedValue, actualValue) ? "Pass" : "Fail";
String status = valueComparator.test(expectedValue, actualValue) ? "Pass" : "Fail";
return rowStatus(entry.getKey().toString(), expectedValue.toString(),
actualValue != null ? actualValue.toString() : "", status);
})
Expand All @@ -115,7 +145,7 @@ public static <K, V> DataTable<String, String> diff(
* @return a table of differences between the expected and actual
* rows
*/
public static <K, V> DataTable<String, String> diff(Map<K, V> expected, Map<K, V> actual) {
public <K, V> DataTable<String, String> diff(Map<K, V> expected, Map<K, V> actual) {
return diff(expected, actual, Collections.emptyList());
}

Expand All @@ -129,7 +159,7 @@ public static <K, V> DataTable<String, String> diff(Map<K, V> expected, Map<K, V
* @return a DataTable containing the differences between the two
* input lists
*/
public static <V> DataTable<String, String> diff(
public <V> DataTable<String, String> diff(
final List<V> expected, final List<V> actual
) {
List<V> sortedExpected = Lists.sortWithNulls(expected);
Expand All @@ -139,7 +169,7 @@ public static <V> DataTable<String, String> diff(
.mapToObj(i -> {
var expectedValue = i < sortedExpected.size() ? sortedExpected.get(i) : null;
var actualValue = i < sortedActual.size() ? sortedActual.get(i) : null;
String status = Objects.equals(expectedValue, actualValue) ? "Pass" : "Fail";
String status = valueComparator.test(expectedValue, actualValue) ? "Pass" : "Fail";
return rowStatus("Row " + i, expectedValue != null ? expectedValue.toString() : "",
actualValue != null ? actualValue.toString() : "", status);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,21 @@ public DataTable<K, V> selectRows(Predicate<Map<K, V>> predicate) {
.collect(Collectors.toCollection(DataTable::new));
}

/**
* Returns a new DataTable containing distinct rows based on the specified
* column.
*
* @param columnName The name of the column used to identify and extract
* distinct rows.
* @return A new DataTable containing only the distinct rows
* based on the specified column.
*/
public DataTable<K, V> distinctByColumn(K columnName) {
return rows()
.collect(Collectors.toMap(row -> row.get(columnName), row -> row, (a, b) -> a))
.values().stream().collect(Collectors.toCollection(DataTable::new));
}

/**
* Joins the current DataTable with another DataTable on the specified join
* column and returns a new DataTable with the combined rows.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import io.github.selcukes.collections.DataComparator;
import io.github.selcukes.collections.DataTable;
import io.github.selcukes.collections.Lists;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

Expand Down Expand Up @@ -46,12 +47,23 @@ public void setup() {
Map.of("id", "4", "Name", "Dave", "Amount", "19,945,711.94", "Type", "Credit"));
}

@Test
public void testWithCustomValueComparator() {
var comparator = DataComparator.create(
(expectedValue, actualValue) -> expectedValue.toString().equalsIgnoreCase(actualValue.toString()));

var one = Lists.of("John", "New York");
var two = Lists.of("JOHN", "New York");
var differences = comparator.diff(one, two);
System.out.println(differences.prettyTable());
}

@Test
public void testCheckTableData() {
var differences = DataComparator.diff(expected, actual, "id", List.of("Type"));
var differences = DataComparator.create().diff(expected, actual, "id", List.of("Type"));
assertEquals(differences.size(), 12);
assertFalse(isFailed(differences));
var differences1 = DataComparator.diff(expected, actual, "id");
var differences1 = DataComparator.create().diff(expected, actual, "id");
assertEquals(differences.size(), 12);
assertTrue(isFailed(differences1));
System.out.println(differences1.prettyTable());
Expand All @@ -62,7 +74,7 @@ public void testCheckRowData() {
var expectedRow = Map.of("id", "1", "Name", "Alice", "Amount", "120,000.00", "Type", "Credit");
var actualRow = Map.of("id", "1", "Name", "Bob", "Amount", "120,000.00", "Type", "Credit");

var differences = DataComparator.diff(expectedRow, actualRow);
var differences = DataComparator.create().diff(expectedRow, actualRow);
assertTrue(isFailed(differences));
System.out.println(differences.prettyTable());
}
Expand All @@ -72,13 +84,13 @@ public void testCheckColumnData() {
var expectedColumn = expected.getColumnEntries("Name");
var actualColumn = actual.getColumnEntries("Name");

var differences = DataComparator.diff(expectedColumn, actualColumn);
var differences = DataComparator.create().diff(expectedColumn, actualColumn);
assertFalse(isFailed(differences));
assertEquals(differences.size(), 4);
System.out.println(differences.prettyTable());
expectedColumn.add("Hello");
actualColumn.add(null);
var differences1 = DataComparator.diff(expectedColumn, actualColumn);
var differences1 = DataComparator.create().diff(expectedColumn, actualColumn);
assertTrue(isFailed(differences1));
assertEquals(differences1.size(), 5);
System.out.println(differences1.prettyTable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ void testGroupByColumn() {
assertTrue(age25Rows.contains(rowE));
}

@Test
public void testDistinctByColumn() {
var newRow = Map.of("Name", "Charlie", "Age", "30", "Country", "USA");
dataTable.addRow(newRow);
var newTable = dataTable.distinctByColumn("Country");
assertFalse(newTable.contains(newRow));
}

@Test(testName = "Test getColumns")
public void testGetColumns() {
assertEquals(Set.copyOf(dataTable.getColumns()), columns);
Expand Down