1

I got a name list that needs to convert to the result that person with same last name are all labeled. For example:

origin list:

JayReese
ClaraSmith
JohnSmith

output:

JayReese
ClaraSmith1
JohnSmith2

The code of Person class are written below, how can I compare all the lastName and when there are duplicated lastName, unique index is added to each? What method should be added?

I'd really appreciate any input and or help. Thank you very much.

import java.util.*;

public class Person implements Comparable<Person> {

    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String toString() {
        return lastName + firstName;
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
SarahP233
  • 13
  • 2
  • `Person` would need to carry a unique index value, which could be sufixed to the output. You also need some kind of lookup which can manage the "next value", so if there was another `Reese`, it wouldn't become `Reese3`, some kind of `Map` should do the trick. You may also need some way to determine if the `Person` already has a unquie identify assigned to it, so if you run across the same instance of `Person` in the `List` you don't increment their identifier – MadProgrammer Jul 23 '15 at 01:06

4 Answers4

0

You could do a compare method like this

public compairLastName(String LastName){
if(lastName.equals(LastName){
System.out.println("These last names are the same"); 
}else{
System.out.println("These last names are not the same");
}
HelloWorld
  • 133
  • 1
  • 15
0

So you asked about labelling (and by extension sorting), but refer to uniquely identifying - here is an answer to both :)

For Sorting

Real life programs deal with that every day, just ensure your comparable code by default sorts by 2 attributes

  1. LastName
  2. FirstName

If they compare in that order, you should end up with:

XavierAllen
JayReese
BillySmith
ClaraSmith
JohnSmith

To compare multiple attributes, I would refer you to this stackoverflow topic, which shows how to do both single and multiple comparisons on a Person object with the same field names even ; )

How to compare objects by multiple fields

For Unique Referance

Also, if you were concerned about uniquely identifying the Person outside of simple comparison sorting, then you would add an int field (or guid, or whatever your flavour) that would hold a unique value

Basically same as a Database PK - you would never use a persons name as a PK in a database, so your Person ideally should have a property like that too.

If you wanted to add this PK to your toString() then go for it

import java.util.*;

public class Person implements Comparable<Person> {

    private int personID;
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName, int personID) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.personID = personID;
    }

    public int getID(){
        return this.personID;
    }

    public String toString() {
        return this.personID + ": " + this.lastName + ", " + this.firstName;
    }
}

@Mshnik did post a method for dynamically adding PK, but youd be much better off checking the Person collection or some high level variable to find the last personID and go from there - else that dynamic value can only be used in the most limited of contexts, and you may as well just use the index its located at in the Person collection you are retrieving it from

Community
  • 1
  • 1
Daniel Brose
  • 1,394
  • 10
  • 24
0

First, either edit the Person class or create a new class that has an index field that can be set. Comparability is completely unnecessary for your usecase.

public class Person {

    private String firstName;
    private String lastName;

    public int index;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String toString() {
        return lastName + firstName + (index != 0 ? index : "");
    }
}

You can use a HashMap<String, Integer> to add the numbering to the last name, like this:

public static void numberDuplicateLastNames(List<Person> people) {
    HashMap<String, Integer> duplicatedLastNames = new HashMap<>();
    for(Person p : people) {
        if(! duplicatedLastNames.containsKey(p.lastName)) {
            duplicatedLastNames.put(p.lastName, 1);
            p.index = 1;
        } else {
            int i = duplicatedLastNames.get(p.lastName) + 1;
            duplicatedLastNames.put(p.lastName, i);
            p.index = i;
        }
    }

    //Remove index from the people who don't have a duplicate last name
    for(Person p : people) {
        if (duplicatedLastNames.get(p.lastName) == 1) {
            p.index = 0;
        }
    }
}
Mshnik
  • 7,032
  • 1
  • 25
  • 38
0

Here's brute force way of labeling your Person objects that doesn't rely on using Maps to count last name occurrences.

I've also include another method to exploit the power of Java 8 streams. IMO, the brute force method is more understandable, but I have not done any benchmark testing to know which is more efficient. So I'll leave that up to commenting.

public static void main(String[] args) throws Exception {
    List<Person> persons = new ArrayList() {
        {
            add(new Person("Jay", "Reese"));
            add(new Person("Clara", "Smith"));
            add(new Person("John", "Smith"));
            add(new Person("James", "Smith"));
            add(new Person("Christie", "Mayberry"));
            add(new Person("Matthew", "Mayberry"));
        }
    };

    // Toggle calls to see results
    bruteForceLabel(persons);
    // java8StreamLabel(persons);
}

public static void bruteForceLabel(List<Person> persons) {
    for (int i = 0; i < persons.size(); i++) {
        Person currentPerson = persons.get(i);
        char lastCharacter = currentPerson.lastName.charAt(currentPerson.lastName.length() - 1);

        // Only process last names that are not labeled
        if (lastCharacter < '0' || '9' < lastCharacter) { // Not a digit
            int counter = 2;
            boolean foundDuplicateLastName = false;

            for (int j = i + 1; j < persons.size(); j++) {
                Person nextPerson = persons.get(j);
                if (nextPerson.lastName.equals(currentPerson.lastName)) {
                    foundDuplicateLastName = true;

                    // Label the next person with the counter then 
                    nextPerson.lastName = nextPerson.lastName + counter;
                    counter++;
                }
            }

            // Label the current person with the starting sequence
            if (foundDuplicateLastName) {
                currentPerson.lastName = currentPerson.lastName + 1;
            }
        }
    }

    System.out.println(persons);
}

public static void java8StreamLabel(List<Person> persons) {
    // Get a distinct count of all last names
    Map<String, Long> lastNames = persons
            .stream()
            .map(p -> p.lastName)
            .distinct()
            .collect(Collectors
                    .toMap(p -> p, p -> persons
                            .stream()
                            .filter(p2 -> p2.lastName.equals(p)).count()));

    // Apply number sequence to duplicate last names
    lastNames.keySet().stream().filter((key) -> (lastNames.get(key) > 1)).forEach((key) -> {
        int counter = 1;
        for (Person person : persons.stream().filter(p -> p.lastName.equals(key)).toArray(size -> new Person[size])) {
            person.lastName = person.lastName + counter;
            counter++;
        }
    });

    // Display the modified list
    System.out.println(persons);
}

public static class Person {

    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String toString() {
        return firstName + " " + lastName;
    }
}

Results:

[Jay Reese, Clara Smith1, John Smith2, James Smith3, Christie Mayberry1, Matthew Mayberry2]
Shar1er80
  • 9,001
  • 2
  • 20
  • 29