views:

83

answers:

2

This is a programming technique problem in the context of Java.

Problem: We have String keys that all need to be unique. The implementation of the collection is a combination of Map and ArrayList which allows one to use the collection as either a Map or ArrayList (JFreeChart's DefaultPieDataset if you are curious). If we have a single piece of data we want it's key to be itself. If we have multiples that are separated by some other key we want the data plus a separator and an incrementing number.

For example:

Data that with two Bob entries and then an Albert would have keys like ["Bob", "Albert"].

Data that looks like Albert and Bob with two Bob entries with an Albert between would have keys like ["Bob : 1", "Albert", "Bob : 2"].

This is our code so far:

String dataKey = "";
DefaultPieDataset ringDataset = new DefaultPieDataset();
for(String thisData: dataList)
{
    int dataValue;
    if(dataKey.equals(thisData))
    {
     dataValue= ringDataset.getValue(dataKey).intValue() + 1;
    }else
    {
     dataKey= thisData;
     if(ringDataset.getKeys().contains(dataKey) || ringDataset.getKeys().contains(dataKey+ " : 1")) //has this name been represented already?
     {
      if(ringDataset.getKeys().contains(dataKey)) //do we need to change the name to accommodate multiples?
      {
       int existingKeyIndex = ringDataset.getIndex(dataKey);
       int existingKeyValue = ringDataset.getValue(dataKey).intValue();
       ringDataset.remove(dataKey);
       ringDataset.insertValue(existingKeyIndex, dataKey+ " : 1", existingKeyValue);
      }

      int counter = 2;
      do{
       dataKey= thisData + " : " + counter;
       counter ++;
      }while(ringDataset.getKeys().contains(dataKey)); //ensure that we are using a new key
     }
     dataValue= 1;
  }
 ringDataset.setValue(dataKey, dataValue);
}

Currently, the code tacks on the " : #" for every duplicate so that instead of Bob : 2 it makes Bob : 1 : 2

An added challenge is that I cannot gurantee that the name will not have the separator (colons in the example).

Also there is extensive red tape required for any libraries added, so a Java API only solution is needed.

Thank you for helping with this particular brain twister,
Adam

Edit: To further clarify the code an items value is based off of the number of times that data type has come up in a row. So in the first example the key Bob has a value of 2 and Albert 1. In the second example all keys have a value of 1.

A: 

I assume you don't have to handle uniqueness of a distributed system since your problem is on the client side. Additionally, I assume you don't have to handle the synchronization on multiple threads. If not, you can consider to put the synchronized keyword in the incrementLabelCount() method, and the performance is probably okay.

I would break your codes into two parts, so it is more manageable:
- part 1: keep tracking of the already known labels - part 2: generate the unique label

Following is the codes that I just type out quickly (without compilation logic)

class KnownLabels
{
  Map<String, Integer> currentCountsByLabel;

  public int incrementLabelCount(String label)
  {
    Integer count = currentCountsByLabel.get(label);
    if(count==null)
      count = 1;
    else
      count += 1;

    currentCountsByLabel.put(label, count);

    return count;
  }
}

class UniqueLabelGenerator
{
  private KnownLabels knownLabels = new KnownLabels();

  public String getUniqueLabel(String label)
  {
    int i = knownLabels.incrementLabelCount(label);

    if(i>1)
      return label + ":" + i;

     return label;
  }
}
Oscar Chan
I agree that breaking up functionality would likely be a good idea as this becomes more complicated. The other clincher though is the need to retroactively change the first instance of a label when a second appears. I like your ideas though and I'll see if I can add the separation.
Adam
A: 

It appears my original code is now working as expected, so sorry for wasting your time and thanks for your help.

Adam