将在列表中迭代时匹配的一个或多个项目分组。

huangapple go评论68阅读模式
英文:

Group one or more matching items while iterating through in a list

问题

如果我需要遍历一个列表并尝试将元素分组在一起,最好的方法是什么?

例如,假设我们有以下要遍历的对象:

People
  |---Person
  |     -FirstName: Jimmy
  |     -LastName: Ward
  |     -Address1: 1 Main Street
  |     -Town: Yipee
  |     -Country: Canada
  |     -Postcode: ABC
  |---Person
  |     -FirstName: Johnny
  |     -LastName: Jones
  |     -Address1: 21 Jump Street
  |     -Town: SomeTownie
  |     -Country: Ireland
  |     -Postcode: ZZZ
  |---...

我需要遍历每个人,并根据具有相同地址和相同姓氏的人创建一个组。

例如,从Jimmy开始,遍历列表以找到具有相同地址和姓氏的任何人,只有Wendy匹配,因此它们会被分组在一起。接下来是Johnny,Tommy是唯一匹配项。

在遍历列表中的剩余人员时,我们不希望为Wendy或Tommy执行相同的过程(因为它们已经被分组)。因此,我们需要从原始列表中删除已经匹配的人,或者以某种方式插入到映射中?

我考虑了一段时间的循环,然后再用循环查找任何匹配项。免责声明:此解决方案用于删除那些匹配项,因此可能不太准确。

例如:

while (!originalPersonList.isEmpty()) {
  ArrayList<Person> newGroup = new ArrayList<Person>();
  List<Integer> indexToRemove = new ArrayList<Integer>();
  newGroup.add(0);
  indexToRemove.add(0);
  for (int i=1; i < originalPersonList.size(); i++) {
    if (originalPersonList.get(0).Address1().equals(originalPersonList.get(i).Address1())
      && originalPersonList.get(0).Town().equals(originalPersonList.get(i).Town())
      && originalPersonList.get(0).Country().equals(originalPersonList.get(i).Country())
      && originalPersonList.get(0).Postcode().equals(originalPersonList.get(i).Postcode())
      && originalPersonList.get(0).Lastname().equals(originalPersonList.get(i).Lastname())) 
    {
       indexToRemove.add(i);
       newGroup.add(i);
    }
  }
  originalPersonList.removeAll(indexToRemove);
}

这是我走向的方向,但我觉得可能有更优雅的解决方案?

我只能使用Java 7。

另外,我尝试搜索类似的问题,但没有与这个特定情景匹配的内容。

英文:

If I need to iterate over a list and try to group elements together, what is the best way to go about this?

Let's say for example we have the following objects to loop through:

People
  |---Person
  |     -FirstName: Jimmy
  |     -LastName: Ward
  |     -Address1: 1 Main Street
  |     -Town: Yipee
  |     -Country: Canada
  |     -Postcode: ABC
  |---Person
  |     -FirstName: Johnny
  |     -LastName: Jones
  |     -Address1: 21 Jump Street
  |     -Town: SomeTownie
  |     -Country: Ireland
  |     -Postcode: ZZZ
  |---Person
  |     -FirstName: Vinny
  |     -LastName: McWhinney
  |     -Address1: 11 Blah Lane 
  |     -Town: Pastaville
  |     -Country: Italy
  |     -Postcode: ALO
  |---Person
  |     -FirstName: Tommy
  |     -LastName: Jones
  |     -Address1: 21 Jump Street
  |     -Town: SomeTownie
  |     -Country: Ireland
  |     -Postcode: ZZZ
  |---Person
  |     -FirstName: Wendy
  |     -LastName: Ward
  |     -Address1: 1 Main Street
  |     -Town: Yipee
  |     -Country: Canada
  |     -Postcode: ABC
  |---Person
  |     -FirstName: Jenny
  |     -LastName: Bloggs
  |     -Address1: 1 Yadda Road
  |     -Town: Blahdeblah
  |     -Country: Ireland
  |     -Postcode: XYZ

I need to go through each person, and create a group with people with the same address and same lastname.

For example, it starts with Jimmy, iterates through the list to find anyone with the same address and lastname, only Wendy matches so they both get grouped together. Next is Johnny, and Tommy is the only match.

When iterating through the remaining people in the list, we do not want to go through the same process for Wendy or Tommy (as they have already been grouped). So we need to remove those that have been matched from the original list, or insert into a map somehow?

I was thinking a while loop, and then for loop to find any matches. Disclaimer: this proposed solution for removing those matching, so could be way off the mark.

For example:

while (!originalPersonList.isEmpty()) {
  ArrayList&lt;Person&gt; newGroup = new ArrayList&lt;Integer&gt;();
  List&lt;Integer&gt; indexToRemove = new ArrayList&lt;Integer&gt;();
  newGroup.add(0);
  indexToRemove.add(0);
  for (int i=1; i &lt; originalPersonList.size(); i++) {
    if (originalPersonList.get(0).Address1().equals( originalPersonList.get(i).Address1())
      &amp;&amp; originalPersonList.get(0).Town().equals(originalPersonList.get(i).Town())
      &amp;&amp; originalPersonList.get(0).Country().equals( originalPersonList.get(i).Country())
      &amp;&amp; originalPersonList.get(0).Postcode().equals( originalPersonList.get(i).Postcode()
      &amp;&amp; originalPersonList.get(0).Lastname().equals( originalPersonList.get(i).Lastname()) 
    {
       indexToRemove.add(i);
       newGroup.add(i);
    }
  }
  originalPersonList.removeAll(indexToRemove);
}

This was the direction I was going towards, but I feel there might be a more elegant solution out there?

I'm restricted to using Java7.

Also I tried searching for similar questions, and there wasn't any matching this particular scenario.

答案1

得分: 2

如@HernánAlarcón所说,地图是您所询问的一个很好的用例场景。所以让我们一步一步来:

创建Person POJO

public class Person {
    private String firstName;
    private String lastName;
    private String address;
    private String town;
    private String country;
    private String postCode;

//Constructor,Getters,Setters ommited for clarity
}

映射需要一个具有适当的哈希码/equals实现的键类。因此,让我们创建一个包含您想要的条件的类:

PersonProjection

public class PersonProjection {
    private String lastname;
    private String address;

    public PersonProjection(String lastname, String address) {
        this.lastname = lastname;
        this.address = address;
    }

    public String getLastname() {
        return lastname;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersonProjection that = (PersonProjection) o;
        return Objects.equals(lastname, that.lastname) && Objects.equals(address, that.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(lastname, address);
    }
}

以下是主要代码,如果没有错误的话,它是兼容Java 7的(8+比这更简单):

public static void main(String[] args) {

    //创建映射
    Map<PersonProjection, List<Person>> map = new HashMap<>();

    List<Person> personList = new ArrayList<>();

    //...填充列表

    for (Person p : personList) {
        //创建投影
        PersonProjection projection = new PersonProjection(p.getLastName(), p.getAddress());

        //每当要插入新键时初始化ArrayList
        if (!map.containsKey(projection))
            map.put(projection, new ArrayList<Person>());

        //将人放入相应的ArrayList中
        map.get(projection).add(p);
    }
}

请注意,此代码未经测试。

英文:

As @HernánAlarcón said, Map is a good use case scenario for what you ask. So let's go step by step:

Creating the Person POJO

public class Person {
    private String firstName;
    private String lastName;
    private String address;
    private String town;
    private String country;
    private String postCode;

//Constructor,Getters,Setters ommited for clarity
}

Maps need a class for a key that has a proper hashcode/equals implementation. So let's create a class which contains the criteria you want:

PersonProjection

public class PersonProjection {
    private String lastname;
    private String address;

    public PersonProjection(String lastname, String address) {
        this.lastname = lastname;
        this.address = address;
    }

    public String getLastname() {
        return lastname;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersonProjection that = (PersonProjection) o;
        return Objects.equals(lastname, that.lastname) &amp;&amp;
                Objects.equals(address, that.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(lastname, address);
    }
}

Below is the main code which is Java 7 compatible if not mistaken (8+ makes things simpler than that):

public static void main(String[] args) {

    //Create map
    Map&lt;PersonProjection, List&lt;Person&gt;&gt; map = new HashMap&lt;&gt;();

    List&lt;Person&gt; personList = new ArrayList&lt;&gt;();

    //...Fill list

    for(Person p : personList)
    {
        //Create the projection
        PersonProjection projection = new PersonProjection(p.getLastName(),p.getAddress());

        //Initialize an arraylist whenever a new key is going to be inserted
        if(!map.containsKey(projection))
            map.put(projection,new ArrayList&lt;Person&gt;());

        //Put the person in the corresponding arraylist
        map.get(projection).add(p);
    }
}

Please note that this code is untested.

huangapple
  • 本文由 发表于 2020年8月18日 05:17:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/63458784.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定