2016-05-16 2 views
0

Я только что занялся программированием, и я пишу программу в java для подсчета голосов, используя Single Transferable Vote. У меня есть мои входные данные в файле Excel, глядя, как это:Создание иерархических данных и добавление их в TreeTableView в JavaFX

this

где имя кандидата отображается на номер под ним в HashTable и каждой строке ниже строк 2 представляет собой один избиратель предпочтение слева направо.

Я хочу, чтобы добавить имена и голоса в TreeTableView ищет что-то вроде этого:

this.

Где каждый кандидат является корнем для своих вторых предпочтений, каждое второе предпочтение является корнем для третьих предпочтений, каждое третье предпочтение является корнем для четвертых предпочтений и т. Д.

Я использую библиотеку apache.poi для использования файлов Excel. Я ищу советы о том, как представлять иерархические данные из листа и как добавить его в TreeTabeView. Как я могу это сделать?

Извините, если это вопрос с вопросом. Я не очень хорошо разбираюсь в том, как использовать иерархические данные. Заранее спасибо!

ответ

0

Используйте класс элементов с 2-мя свойствами

  • кандидата
  • подсчета голосов

будет делать трюк (= один свойство в столбце). Например.

public class VoteEntry { 

    // candidate INDEX 
    private final IntegerProperty candidate; 

    private final IntegerProperty voteCount; 

    public VoteEntry(int candidate, int count) { 
     this.voteCount = new SimpleIntegerProperty(count); 
     this.candidate = new SimpleIntegerProperty(candidate); 
    } 

    public final int getCandidate() { 
     return this.candidate.get(); 
    } 

    public final void setCandidate(int value) { 
     this.candidate.set(value); 
    } 

    public final IntegerProperty candidateProperty() { 
     return this.candidate; 
    } 

    public final int getVoteCount() { 
     return this.voteCount.get(); 
    } 

    public final void setVoteCount(int value) { 
     this.voteCount.set(value); 
    } 

    public final IntegerProperty voteCountProperty() { 
     return this.voteCount; 
    } 

} 

Вы можете сгруппировать голоса на меньшие и меньшие подгруппы для создания TreeItem иерархии:

private final List<int[]> votes = new ArrayList<>(); 

private void addVote(int... preferences) { 
    // convert to array of candidate indices sorted descendingly by preference 
    int[] votes = new int[preferences.length]; 
    for (int i = 0; i < preferences.length; i++) { 
     votes[preferences[i] - 1] = i; 
    } 
    this.votes.add(votes); 
} 

private static void createHierarchy(TreeItem<VoteEntry> parent, List<int[]> votes, int index) { 
    int max = votes.stream().mapToInt(a -> a.length).max().getAsInt(); 
    if (max > index) { 
     // group by candidate 
     Map<Integer, List<int[]>> groups = votes.stream().collect(Collectors.groupingBy(a -> a.length > index ? a[index] : -1)); 
     groups.forEach((candidate, vts) -> { 
      if (candidate != -1) { 
       VoteEntry entry = new VoteEntry(candidate, vts.size()); 
       TreeItem<VoteEntry> item = new TreeItem<>(entry); 
       parent.getChildren().add(item); 
       createHierarchy(item, vts, index + 1); 
      } 
     }); 

     // sort by candidate 
     parent.getChildren().sort(Comparator.comparingInt(ti -> ti.getValue().getCandidate())); 
    } 
} 

@Override 
public void start(Stage primaryStage) { 
    addVote(1, 2, 3, 4); 
    addVote(4, 3, 2, 1); 
    addVote(1, 3, 2, 4); 
    addVote(2, 1, 4, 3); 
    addVote(2, 4, 3, 1); 
    addVote(2, 1, 3, 4); 
    // ... 

    ObservableList<String> candidateNames = FXCollections.observableArrayList(
      "Candidate 1", 
      "Candidate 2", 
      "Candidate 3", 
      "Candidate 4" 
      ); 

    TreeItem<VoteEntry> root = new TreeItem<>(); 
    createHierarchy(root, votes, 0); 

    TreeTableView<VoteEntry> view = new TreeTableView<>(root); 
    view.setShowRoot(false); 

    TreeTableColumn<VoteEntry, String> candidateColumn = new TreeTableColumn<>("candidate"); 
    candidateColumn.setCellValueFactory(data -> Bindings.valueAt(candidateNames, data.getValue().getValue().candidateProperty())); 

    TreeTableColumn<VoteEntry, Integer> votesColumn = new TreeTableColumn<>("votes"); 
    votesColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("voteCount")); 

    view.getColumns().addAll(candidateColumn, votesColumn); 

    Scene scene = new Scene(view); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

Обратите внимание, что рекурсивный подход работает только для ограниченного количества кандидатов (stackoverflows). Но он должен работать на разумные номера кандидатов (пользователь не захочет расширять сотни предметов ...).

+0

Большое спасибо! Работал, но я заметил одну проблему. Преобразование int ... prefrences в массив не работает должным образом. Исправлено, изменив код внутри цикла for на «vote [i] = предпочтения [i] -1;». –

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