5

I have a list of objects and i want to process subset of objects based on condition and then create a new list with processed objects.

The List if Objects

miss | shannon sperling
mr | john smith
prof | kim taylor
prof.dr | kim taylor

In the above list i want to the names which has two titles(kim taylor) and glue the title because prof is a subset of prof.dr. My final list should look like the following

miss | shannon sperling
mr | john smith
prof.dr | kim taylor  

I tried with following code

void gluetitles(List title)
       {
           for (int i=0;i<title.size();i++) { 
                String names = (String) title.get(i);
                String[] titlename=names.split("\\|");\\split the list with delimiter and extracts titles and names
                String tle=titlename[0];
                String name=titlename[1];

           }     
       }

But i did not get idea how to compare and get the name which has two titles.

13
  • do you mean mr | kim taylor and prof | kim taylor Commented Nov 7, 2013 at 9:02
  • So you want to combine records that share the same name? Commented Nov 7, 2013 at 9:03
  • 2
    Consider using a map, and storing titleName[1] as the key and appending the new title if it doesn't already contain it. Commented Nov 7, 2013 at 9:04
  • i would like to glue the title of "prof kim taylor" and "prof.dr. kim taylor" into one "prof.dr.Kim taylor" Commented Nov 7, 2013 at 9:05
  • 1
    @MarcelPuyat An interesting thought, but she also hasn't said what would happen if a person had two titles such that neither contained the other. That wouldn't work if she wants the titles concatenated in some way. Commented Nov 7, 2013 at 9:20

5 Answers 5

1

This code works fine...

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class Notepad {

    public static void main(String args[]) {
        final List<String> titles = new ArrayList<>();
        titles.add("miss | shannon sperling");
        titles.add("mr | john smith");
        titles.add("prof | kim taylor");
        titles.add("prof.dr | kim taylor");
        gluetitles(titles);
    }

    static void gluetitles(final List<String> titles) {
        final Map<String, String> titleMap = new HashMap<>();
        for (final String names : titles) {
            final String[] titleName = names.split("\\|");
            final String title = titleName[0];
            final String name = titleName[1];
            if (doesMapContainName(titleMap, title, name)) {
                titleMap.put(name, title);
            }
        }
        for (final Entry<String, String> s : titleMap.entrySet()) {
            System.out.println("Name is " + s.getKey() + " Title is "
                    + s.getValue());
        }
    }

    private static boolean doesMapContainName(
            final Map<String, String> titleMap, final String title,
            final String name) {
        return (titleMap.get(name) != null && titleMap.get(name).length() < title
                .length()) || !titleMap.containsKey(name);
    }
}

The contain method is a bit dirty but the long and short of it is if it exists in the map, check if this new value is longer than the one we already know about, if it is, add it, if it doesn't exist in the map, add it. This assumes the data always just concatenates the titles like in the example, we have one with prof.dr and one with prof.

Sign up to request clarification or add additional context in comments.

3 Comments

:How do i convert this titleMap back list with same format.When i tried to convert this map into list, the list prints either keys or values but not both.
You would need a print(Map<String, String>) method that just loops through the map, putting the key at the start, appending the pipe character and then append the value.
Can i put the key,pipe char and value directly into list.add() or assign to string.Assign to sting works fine.But adding to list raising nullpointerexception
1

Here is the code that create a map with the name as a key and the title as value. After the map is created you should build the list you need concatening the value of the map with the key

 void gluetitles(List title)
    {
        Map<String, String> titleNamesMap = new TreeMap<String, String>();
        for (int i=0;i<title.size();i++) { 
             String names = (String) title.get(i);
             String[] titlename=names.split("\\|");//split the list with delimiter and extracts titles and names
             String tle=titlename[0];
             String name=titlename[1];
             if(titleNamesMap.containsKey(name)){
                 String oldTitle = titleNamesMap.get(name);
                 if(!oldTitle.contains(tle)){
                     String newTle = (tle+".").concat(oldTitle);
                     titleNamesMap.put(name,newTle);
                 }
             }else{
                 titleNamesMap.put(name, tle);
             }
        }
    }

Hope it will be useful for you.

4 Comments

Concatenating the titles with . doesn't seem like the right way to go there, the example input I think gets prof.dr.prof | kim taylor with that approach instead of just prof.dr | kim taylor.
You're right. I didn't see that. The code should check if the new title is already in the map. I'll change the code. Thanks.
No it doesn't, if the order is prof.dr before prof in the list, you end up with prof .prof.dr - unless that's what you want.
@david99world:yes you are true.Your code is working in other scenario too.
0

You could use another for-loop within the for-loop you already have to compare the title of the current String to the title of other Strings in your list. You just have to make sure not to compare the string to itself by skipping over the same index with a continue. Like so:

void gluetitles(List title)
   {
       for (int i=0;i<title.size();i++) { 
            String names = (String) title.get(i);
            String[] titlename=names.split("\\|");
            String tle=titlename[0];
            String name=titlename[1];

            for (int j = 0; j < title.size(); j++) {
                if (j == i) continue; // This makes sure you don't compare it to itself.

                ...split the string here...

                if (secondTitle.contains(tle)) --> process what you want.
            }
       }     
   }

I'm not sure about the .contains method, but simply look for a String method that finds subsets.

1 Comment

.contains is fine, though if you are only interested if a string is a prefix of another, there's startsWith.
0

Do like this

Your Comparator

class SimpleComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.split("\\|")[1].trim().compareTo(o2.split("\\|")[1].trim());
    }
}

Your data

List<String> list = new ArrayList<String>();
list.add("miss | shannon sperling");
list.add("mr | john smith");
list.add("prof | kim taylor");
list.add("prof.dr | kim taylor");

Filtering the data

Set<String> s = new TreeSet<String>(new SimpleComparator());
s.addAll(list);
System.out.println(s);

output

mr | john smith
prof | kim taylor
miss | shannon sperling

Comments

0

Basically what I would do is use a Map of some kind. That would look something like this:

void gluetitles(List<String> title) {
    Map<String, String> map = new HashMap<String,String>();
    for (int i=0;i<title.size();i++) { 
        String names = (String) title.get(i);
        String[] titlename = names.split("\\|");
        String tle = titlename[0];
        String name = titlename[1];

        if(map.containsKey(name)) {
            String savedTitle = map.get(name);
            if(isBetterTitle(tle, savedTitle)) { // compare your savedTitle to the given one here
                map.put(name, tle);
            }
        } else {
            map.put(name, tle);
        }
    }

    for(Iterator<String> it = map.keySet().iterator(); it.hasNext(); ) {
        String name = it.next();
        System.out.println(map.get(name) + name);
    }
}

boolean isBetterTitle(String tle1, String tle2) {
    return tle1.replaceAll(" ", "").contains(tle2.replaceAll(" ", ""));
}

1 Comment

For what it's worth, there's no need to call remove before put, put replaces any entry that was there with the entry that you give it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.