Reputation: 3
I have to compare lines of two separate files and output the result (saved into a separate List) in a specific manner. File1 is the original text. File2 either has some of the same lines or new lines. Meaning that some lines that are present in File1 are missing in File2.
For example:
File1:
A
B
C
D
E
File2:
B
C
D
F
G
Output of the combined list before custom sort:
A - Removed
B - Same
C - Same
D - Same
E - Removed
F - New
G - New
What I need to do is output the list in the following manner:
A - Removed
B - Same
E - Removed
C - Same
F - New
D - Same
G - New
Basically, the lines that are the same need to be shown (or saved initially?) on every second index.
I have so far managed to compare the files (by adding lines from each file to two separate linked lists and comparing them) and created a combined List with a line status (i.e. same, removed, new) added to each line.
However, I just can't get my head round the algorithm for this kind of custom sort, as I am new to Java.
Do I need to create a custom Iterator and pass it to my combined List? Or can this be achieved with the default listIterator?
Code so far:
public class Solution {
public static List<LineItem> lines = new ArrayList<>();
public static void main(String[] args) {
try (BufferedReader fileOne = new BufferedReader(new FileReader("file1.txt"));
BufferedReader fileTwo = new BufferedReader(new FileReader("file2.txt"))) {
List<String> listOne = new LinkedList<>();
List<String> listTwo = new LinkedList<>();
List<LineItem> listOfSame = new LinkedList<>();
List<LineItem> result = new ArrayList<>();
String line;
while ((line = fileOne.readLine()) != null) {
listOne.add(line);
}
while ((line = fileTwo.readLine()) != null) {
listTwo.add(line);
}
for (String s : listOne) {
if (listTwo.contains(s)) {
listOfSame.add(new LineItem(Type.SAME, s));
} else if (!listTwo.contains(s)) {
lines.add(new LineItem(Type.REMOVED, s));
}
}
for (String s : listTwo) {
if (!listOne.contains(s)) {
lines.add(new LineItem(Type.ADDED, s));
}
}
Iterator<LineItem> itSame = listOfSame.iterator();
for (int i = 0; i < lines.size(); i++) {
result.add(lines.get(i));
if (i % 2 == 0 && itSame.hasNext()) {
result.add(itSame.next());
}
}
while (itSame.hasNext()) {
result.add(itSame.next());
}
for (LineItem item : result) {
System.out.println(item.type.toString() + " " + item.line);
}
} catch (IOException e) { e.printStackTrace(); }
}
public static enum Type {
ADDED, // New line added
REMOVED, // Line deleted
SAME // No change
}
public static class LineItem {
public Type type;
public String line;
public LineItem(Type type, String line) {
this.type = type;
this.line = line;
}
}
}
Upvotes: 0
Views: 69
Reputation: 3083
I suppose you could move the SAME
items into a separate list and then go through both lists and output a SAME
line every other iteration (doing a pseudo merge sort). Something like:
List<LineItem> sameOnes = new ArrayList();
Iterator<LineItem> it = lines.iterator();
while (it.hasNext()) {
LineItem item = it.next();
if (item.type == Type.SAME) {
sameOnes.add(item);
it.remove();
}
}
And then:
List<LineItem> result = new ArrayList<>();
Iterator<LineItem> sameIt = sameOnes.iterator();
for (int i = 0; i < lines.size(); i++) {
result.add(lines.get(i));
// Ensure there still are same lines to output
if (sameIt.hasNext()) {
result.add(sameIt.next());
}
}
// Fill in the rest in case there were more same than different lines
while (sameIt.hasNext()) {
result.add(sameIt.next());
}
Upvotes: 0