Skip to content

Commit 81e0f42

Browse files
committed
Update readme and add using Union find algorithm on PHP
1 parent 595d687 commit 81e0f42

File tree

4 files changed

+61
-82
lines changed

4 files changed

+61
-82
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
Alhoritm
2+
--
3+
[Disjoint-set/Union-find Forest](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)
4+
15
Problem/Motivation
26
--
37
Find duplicates in CSV file. The problem was the related search for duplicates in the data table. On demand there is a need to find a duplicate from key fields (in any field) and to assign the first duplicate occurrence to **PARENT_ID**.
48

5-
The algorithm finding a chain of duplicates and generates result with **ID** and **PARENT_ID** was created.
9+
Union find algorithm implemented on PHP, finding a chain of duplicates and generates result with **ID** and **PARENT_ID** was created.
610

711
Example of input data (based on the csv file):
812
```

README_RU.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
Alhoritm
2+
--
3+
[Disjoint-set/Union-find Forest](https://ru.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%81%D0%B5%D0%BA%D0%B0%D1%8E%D1%89%D0%B8%D1%85%D1%81%D1%8F_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2)
4+
15
Problem/Motivation
26
--
3-
Поиск дубликатов в CSV файле. Суть задачи состояла в связанном поиска дубликатов в таблице с данными. По требованиям нужно найти из ключевых полей дубликат (в любом поле) и присвоить записи **PARENT_ID** первого вхождения дубликата. Был написан алгоритм который находит дубликаты связывает их и формирует результат с **ID** и **PARENT_ID**.
7+
Поиск дубликатов в CSV файле. Суть задачи состояла в связанном поиска дубликатов в таблице с данными. По требованиям нужно найти из ключевых полей дубликат (в любом поле) и присвоить записи **PARENT_ID** первого вхождения дубликата. Было решено использовать **Union find**, алгоритм который реализовали на PHP находит дубликаты связывает их и формирует результат с **ID** и **PARENT_ID**.
48

59
Пример входных данных (за основу взят файл csv):
610
```

README_UA.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
Alhoritm
2+
--
3+
[Disjoint-set/Union-find Forest](https://uk.wikipedia.org/wiki/%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_%D0%BD%D0%B5%D0%BF%D0%B5%D1%80%D0%B5%D1%82%D0%B8%D0%BD%D0%BD%D0%B8%D1%85_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B8%D0%BD)
4+
15
Problem/Motivation
26
--
37
Пошук дублікатів в CSV файлі. Суть задачі полягала в зв'язаному пошуку дублікатів в таблиці з даними. По вимогам потрібно знайти з ключових полів дублікат (в будь якому полі) і присвоїти запису **PARENT_ID** першого входження дубліката.
48

5-
Був написаний алгоритм на PHP який знаходить дублікати зв'язує їх і формує результат з **ID** та **PARENT_ID**.
9+
Вирішено було використати **Union find** алгоритм написаний на PHP який знаходить дублікати зв'язує їх і формує результат з **ID** та **PARENT_ID**.
610

711
Приклад вхідних даних (за основу взятий файл csv):
812
```

index.php

Lines changed: 46 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
/**
33
* Find Chain of duplicates in a CSV file.
44
*
5-
* @author Roman Zakharchuk <extatic.dancer@gmail.com>
65
* @author Volodymyr Melnychuk <540991@i.ua>
76
*
87
*/
98

9+
// Define constants.
10+
define('FIELDS', ['EMAIL', 'CARD', 'PHONE']);
11+
1012
// Default example data.
1113
$csv = 'ID,PARENT_ID,EMAIL,CARD,PHONE,TMP
1214
1,NULL,email1,card1,phone1,
13-
2,NULL,email2,card2,phone2,
15+
2,NULL,email2,card1,phone2,
1416
3,NULL,email3,card3,phone3,
1517
4,NULL,email1,card2,phone4,
1618
5,NULL,email5,card5,phone2,
@@ -36,97 +38,62 @@
3638
];
3739
}
3840

39-
// Get all rows for fields.
40-
$ids = array_column($fields_array, 'ID');
41-
$emails = array_column($fields_array, 'EMAIL');
42-
$cars = array_column($fields_array, 'CARD');
43-
$phones = array_column($fields_array, 'PHONE');
44-
45-
$results = [];
4641
$csv_string = 'ID,PARENT_ID' . PHP_EOL;
4742

48-
// Prepare data for csv.
43+
$mapping_fields = [];
44+
45+
// Find duplicates and save to mapping.
4946
foreach ($fields_array as $key => $array) {
5047

51-
$ids_by_mail = get_duplicate_array($emails, 'EMAIL', $array['EMAIL']);
52-
$ids_by_card = get_duplicate_array($cars, 'CARD', $array['CARD']);
53-
$ids_by_phone = get_duplicate_array($phones, 'PHONE', $array['PHONE']);
48+
// Skip first element in array.
49+
if ($key === 0) {
50+
continue;
51+
}
52+
53+
// Set default value for each iteration.
54+
$group = NULL;
55+
$group_to_merge = [];
5456

55-
$min_ids = [
56-
min($ids_by_mail),
57-
min($ids_by_card),
58-
min($ids_by_phone),
59-
];
57+
// Grouping by fields.
58+
foreach (FIELDS as $field) {
59+
$field_value = $array[$field];
60+
if (array_key_exists($array[$field], $mapping_fields)) {
61+
$group = $mapping_fields[$field_value];
62+
$group_to_merge[] = $group;
63+
}
64+
}
6065

61-
$min_id = min($min_ids);
66+
// Setting minimal group if have more one group ID.
67+
if (count($group_to_merge) > 1) {
68+
$group = min($group_to_merge);
69+
}
70+
71+
// Setting group if do not have any duplicates.
72+
if ($group === NULL) {
73+
$group = $array['ID'];
74+
}
6275

63-
fill_results($ids_by_mail, $results, $min_id);
64-
fill_results($ids_by_card, $results, $min_id);
65-
fill_results($ids_by_phone, $results, $min_id);
76+
// Save fields to mapping.
77+
$mapping_fields[$array['EMAIL']] = $group;
78+
$mapping_fields[$array['CARD']] = $group;
79+
$mapping_fields[$array['PHONE']] = $group;
6680

6781
}
6882

69-
ksort($results);
83+
foreach ($fields_array as $key => $array) {
84+
// Skip first element in array.
85+
if ($key === 0) {
86+
continue;
87+
}
88+
// Searching PARENT_ID by email field. May be any field (like: CARD, PHONE).
89+
$fields_array[$key]['PARENT_ID'] = $mapping_fields[$array['EMAIL']];
7090

71-
// Prepare string for csv.
72-
foreach ($results as $key => $result) {
91+
// Prepare data from csv.
7392
if ($key !== 0) {
74-
$csv_string .= implode(',', [$key, $results[$key]['PARENT_ID']]) . PHP_EOL;
93+
$csv_string .= implode(',',
94+
[$key, $fields_array[$key]['PARENT_ID']]) . PHP_EOL;
7595
}
7696
}
7797

78-
//print_r($results);
7998
// Show results as string.
8099
print_r($csv_string);
81-
82-
/**
83-
* Return founded duplicates key.
84-
*
85-
* @param array $array
86-
* Array with fields.
87-
* @param $column
88-
* Field name.
89-
* @param $string
90-
* Search string.
91-
*
92-
* @return array|bool
93-
*/
94-
function get_duplicate_array($array, $column, $string) {
95-
96-
$results = array_filter($array,
97-
function ($value) use ($string) {
98-
if ($value === $string) {
99-
return TRUE;
100-
}
101-
return FALSE;
102-
},
103-
ARRAY_FILTER_USE_BOTH);
104-
105-
$results = array_fill_keys(array_keys($results), min(array_keys($results)));
106-
107-
if (count($results) > 0) {
108-
return $results;
109-
}
110-
else {
111-
return [];
112-
}
113-
114-
}
115-
116-
/**
117-
* Get fill results.
118-
*
119-
* @param $array
120-
* Array.
121-
* @param $results
122-
* Row results.
123-
* @param $min_id
124-
* Minimal ID.
125-
*/
126-
function fill_results($array, &$results, $min_id) {
127-
foreach ($array as $id => $value) {
128-
if (empty($results[$id]) || $results[$id] > $min_id) {
129-
$results[$id]['PARENT_ID'] = $min_id;
130-
}
131-
}
132-
}

0 commit comments

Comments
 (0)