Преобразование данных - PullRequest
4 голосов
/ 10 июня 2010

У меня есть данные, состоящие из списка employers и списка workers.Каждый из них имеет отношение «многие ко многим» с другим (поэтому у работодателя может быть много работников, а у работника может быть много работодателей).

Способ, которым данные извлекаются (и передаются мне), таков:следует: каждый employer имеет массив workers.Другими словами:

employer n has:
  worker x, worker y etc.

Итак, у меня есть куча объектов работодателей, каждый из которых содержит массив работников.

Мне нужно преобразовать эти данные (и в основном инвертировать отношения).Мне нужно иметь кучу worker объектов, каждый из которых содержит массив employers.Другими словами:

worker x has:
  employer n1, employer n2 etc.

Контекст является гипотетическим, поэтому, пожалуйста, не комментируйте, почему мне это нужно или почему я делаю это таким образом.Мне бы очень хотелось, чтобы справка по алгоритму выполняла это преобразование ( не так много данных), поэтому я бы предпочел удобочитаемость по сравнению со сложной оптимизацией, которая уменьшает сложность).(О, и я использую Java, но псевдокод будет в порядке).

Ответы [ 2 ]

4 голосов
/ 10 июня 2010

Вы хотите Map<Worker,Set<Employer>> для этого или, возможно, Multimap<Worker,Employer> из Гуавы.

В псевдокоде:

initialize employerMap(worker => set of employers)
for every employer n do
    for every worker x in n.workers do
         employerMap[x].add(n)

По существу, Worker может быть сопоставлен с несколькими Employer, поэтому вы можете:

  • иметь Map<Worker,Set<Employer>>
    • , каждая клавиша в Map может иметь только одинзначение, поэтому значение в этом случае представляет собой Set значений
  • Имеет Multimap<Worker,Employer>
    • Multimap может сопоставить ключ с несколькими значениями

Пример

Вот пример выполнения сопоставления.Обратите внимание, что хранить данные в Object[][] arr, как это, определенно не рекомендуется, и используется только как часть примера.Сконцентрируйтесь на фактической части сопоставления.

import java.util.*;
public class MultiMapExample {
    public static void main(String[] args) {
        Object[][] arr = {
            { "IBM",    new String[] { "Joe", "Jack", "Carol"   }},
            { "MS",     new String[] { "Jack", "Andy", "Carol" }},
            { "Google", new String[] { "Bob", "Alice", "Carol"  }},
        };
        Map<String,Set<String>> employerMap =
            new HashMap<String,Set<String>>();

        for (Object[] data : arr) {
            String employer = (String) data[0];
            String[] workers = (String[]) data[1];
            for (String worker : workers) {
                Set<String> employers = employerMap.get(worker);
                if (employers == null) {
                    employerMap.put(worker, employers = new HashSet<String>());
                }
                employers.add(employer);
            }
        }

        for (String worker : employerMap.keySet()) {
            System.out.println(worker + " works for " + employerMap.get(worker));
        }
    }
}

Это печатает (порядок может отличаться):

Alice works for [Google]
Jack works for [IBM, MS]
Bob works for [Google]
Andy works for [MS]
Carol works for [IBM, Google, MS]
Joe works for [IBM]

Я рекомендую хранить данные в Map, как это, но если вы должныпо какой-то причине преобразовать список сотрудников в массив, вы можете использовать Collection.toArray(T[]).

Однако вы, как правило, предпочитаете List и другие классы Java Collections Framework массивам.


О реализации equals, hashCode и т. Д.

В приведенном выше примере для простоты используется String.Вы, вероятно, должны вместо этого иметь фактические типы Worker и Employer, что хорошо.Вы должны убедиться, что они правильно реализуют equals и hashCode.

См. Также

  • Effective Java 2nd Edition
    • Пункт 8: Соблюдайте общий контракт, если переопределение равно
    • Пункт 9: Всегда переопределять хэш-код, когда переопределение равно

API ссылки

Смежные вопросы

Вкл. equals/hashCode комбинированный:

Вкл. equals против ==:

3 голосов
/ 10 июня 2010

Не специфично для java, но вот подход:

  • сделать словарь из <Worker, Set<Employer>>,
  • итерировать всех работников каждого работодателя и
  • для каждого работника, добавьте текущего работодателя в Dict[Worker] набор

. Вам нужно будет добавить проверку, чтобы создать набор при первом обнаружении каждого работника.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...