Change matrix structure

Asked

Viewed 143 times

-2

How to change the structure of an array? It can be using excel or via programming. I have already made my solution with Java but it was a lot :). Also not generic enough.

Is there a Pattern design, or data structure concept that solves this? The ultimate goal is to be able to sort the table by date, which is not possible with the table in the initial format.

tabelas

  • Could better define your doubt, your question is a little wide

  • Table 1 represents an activity that happens at a certain date and place, it is necessary to rearrange the contents of table 1, in the format of table 2, so that you can view the activities ordered by date. The solution can be using some programming language or excel. I was able to explain better?

1 answer

1

Let’s create a class first Tabela:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;

class Tabela<L, C, X> {
    private final Set<C> colunas;
    private final Set<L> linhas;
    private final Map<L, Map<C, X>> celulas;
    private final Function<? super L, String> strLinhas;
    private final Function<? super C, String> strColunas;
    private final Function<? super X, String> strCelulas;

    @FunctionalInterface
    public static interface TabelaConsumer<L, C, X> {
        public void accept(L linha, C coluna, X celula);
    }

    public Tabela(
            Collection<L> linhas,
            Collection<C> colunas,
            Function<? super L, String> strLinhas,
            Function<? super C, String> strColunas,
            Function<? super X, String> strCelulas)
    {
        this.colunas = new LinkedHashSet<>(colunas);
        this.linhas = new LinkedHashSet<>(linhas);
        this.strLinhas = strLinhas;
        this.strColunas = strColunas;
        this.strCelulas = strCelulas;
        this.celulas = new LinkedHashMap<>(this.linhas.size());
        for (L linha : this.linhas) {
            Map<C, X> valoresLinha = new LinkedHashMap<>(this.colunas.size());
            for (C coluna : this.colunas) {
                valoresLinha.put(coluna, null);
            }
            this.celulas.put(linha, valoresLinha);
        }
    }

    public void put(L linha, C coluna, X valor) {
        if (!linhas.contains(linha) || !colunas.contains(coluna)) throw new IllegalArgumentException();
        celulas.get(linha).put(coluna, valor);
    }

    public X get(L linha, C coluna) {
        if (!linhas.contains(linha) || !colunas.contains(coluna)) return null;
        return celulas.get(linha).get(coluna);
    }

    public void forEach(TabelaConsumer<? super L, ? super C, ? super X> consumer) {
        for (L linha : linhas) {
            for (C coluna : colunas) {
                consumer.accept(linha, coluna, get(linha, coluna));
            }
        }
    }

    private List<Integer> calcularLargura() {
        List<Integer> lista = new ArrayList<>(colunas.size() + 1);

        int m = 0;
        for (L linha : linhas) {
            int x = strLinhas.apply(linha).length();
            if (x > m) m = x;
        }
        lista.add(m);

        for (C coluna : colunas) {
            int n = strColunas.apply(coluna).length();
            for (L linha : linhas) {
                X celula = get(linha, coluna);
                int x = celula == null ? 0 : strCelulas.apply(celula).length();
                if (x > n) n = x;
            }
            lista.add(n);
        }

        return lista;
    }

    private void imprimirSeparador(StringBuilder sb, int tamanho) {
        sb.append("+-");
        for (int i = 0; i <= tamanho; i++) {
            sb.append('-');
        }
    }

    private void imprimirSeparador(StringBuilder sb, List<Integer> tamanhos) {
        for (int i : tamanhos) {
            imprimirSeparador(sb, i);
        }
        sb.append("+\n");
    }

    private void imprimirCelula(StringBuilder sb, int tamanho, String conteudo) {
        sb.append("| ").append(conteudo);
        for (int i = conteudo.length(); i <= tamanho; i++) {
            sb.append(' ');
        }
    }

    private void imprimirCabecalho(StringBuilder sb, List<Integer> tamanhos) {
        Iterator<Integer> it = tamanhos.iterator();
        imprimirCelula(sb, it.next(), "");
        for (C coluna : colunas) {
            imprimirCelula(sb, it.next(), strColunas.apply(coluna));
        }
        sb.append("|\n");
    }

    private void imprimirLinha(StringBuilder sb, List<Integer> tamanhos, L linha) {
        Iterator<Integer> it = tamanhos.iterator();
        imprimirCelula(sb, it.next(), strLinhas.apply(linha));
        for (C coluna : colunas) {
            X celula = get(linha, coluna);
            imprimirCelula(sb, it.next(), celula == null ? "" : strCelulas.apply(celula));
        }
        sb.append("|\n");
    }

    @Override
    public String toString() {
        List<Integer> tamanhos = calcularLargura();
        int larguraTotal = tamanhos.stream().reduce(0, Integer::sum) + 3 * tamanhos.size() + 2;
        StringBuilder sb = new StringBuilder(larguraTotal * (linhas.size() * 2 + 3));
        imprimirSeparador(sb, tamanhos);
        imprimirCabecalho(sb, tamanhos);
        imprimirSeparador(sb, tamanhos);
        for (L linha : linhas) {
            imprimirLinha(sb, tamanhos, linha);
            imprimirSeparador(sb, tamanhos);
        }
        return sb.toString();
    }
}

This class is generic. Having it, then we will use for your data the classes Local and Atividade as well as the java.time.LocalDate for the contents of the table:

class Local {
    private final String nome;

    public Local(String nome) {
        this.nome = nome;
    }

    @Override
    public String toString() {
        return nome;
    }
}

class Atividade {
    private final String nome;

    public Atividade(String nome) {
        this.nome = nome;
    }

    @Override
    public String toString() {
        return nome;
    }
}

Finally, the code that uses all this, creating table 1 and transforming it into table 2:

class Teste {

    private static final DateTimeFormatter FMT = DateTimeFormatter
            .ofPattern("dd/MM/uuuu")
            .withResolverStyle(ResolverStyle.STRICT);

    public static void main(String[] args) {

        // Define os locais e atividades.
        Local casa = new Local("Casa");
        Local escola = new Local("Escola");
        Local trabalho = new Local("Trabalho");
        Atividade estudo = new Atividade("Estudo");
        Atividade treino = new Atividade("Treino");
        Atividade apresentacao = new Atividade("Apresentação");

        // Define a estrutura da tabela 1.
        Tabela<Atividade, Local, LocalDate> tabela1 = new Tabela<>(
                Arrays.asList(estudo, treino, apresentacao),
                Arrays.asList(casa, escola, trabalho),
                Object::toString,
                Object::toString,
                ld -> ld.format(FMT)
        );

        // Preenche a tabela 1.
        tabela1.put(estudo, casa, LocalDate.of(2017, 2, 1));
        tabela1.put(estudo, escola, LocalDate.of(2017, 3, 10));
        tabela1.put(estudo, trabalho, LocalDate.of(2017, 1, 1));
        tabela1.put(treino, casa, LocalDate.of(2017, 5, 3));
        tabela1.put(treino, escola, LocalDate.of(2017, 2, 4));
        tabela1.put(treino, trabalho, LocalDate.of(2017, 5, 1));
        tabela1.put(apresentacao, casa, LocalDate.of(2017, 2, 2));
        tabela1.put(apresentacao, escola, LocalDate.of(2017, 3, 3));
        tabela1.put(apresentacao, trabalho, LocalDate.of(2017, 12, 10));

        // Mostra a tabela 1.
        System.out.println("Tabela 1:");
        System.out.println(tabela1);

        // Descobre as datas que são linhas da tabela 2.
        Set<LocalDate> datas = new TreeSet<>();
        tabela1.forEach((atividade, local, data) -> datas.add(data));

        // Define a estrutura da tabela 2.
        Tabela<LocalDate, Atividade, Local> tabela2 = new Tabela<>(
                datas,
                Arrays.asList(estudo, treino, apresentacao),
                ld -> ld.format(FMT),
                Object::toString,
                Object::toString
        );

        // Preenche a tabela 2 com base nos dados da tabela 1.
        tabela1.forEach((atividade, local, data) -> tabela2.put(data, atividade, local));

        // Mostra a tabela 2.
        System.out.println("Tabela 2:");
        System.out.println(tabela2);
    }
}

Here’s the way out:

Tabela 1:
+--------------+------------+------------+------------+
|              | Casa       | Escola     | Trabalho   |
+--------------+------------+------------+------------+
| Estudo       | 01/02/2017 | 10/03/2017 | 01/01/2017 |
+--------------+------------+------------+------------+
| Treino       | 03/05/2017 | 04/02/2017 | 01/05/2017 |
+--------------+------------+------------+------------+
| Apresentação | 02/02/2017 | 03/03/2017 | 10/12/2017 |
+--------------+------------+------------+------------+

Tabela 2:
+------------+----------+----------+--------------+
|            | Estudo   | Treino   | Apresentação |
+------------+----------+----------+--------------+
| 01/01/2017 | Trabalho |          |              |
+------------+----------+----------+--------------+
| 01/02/2017 | Casa     |          |              |
+------------+----------+----------+--------------+
| 02/02/2017 |          |          | Casa         |
+------------+----------+----------+--------------+
| 04/02/2017 |          | Escola   |              |
+------------+----------+----------+--------------+
| 03/03/2017 |          |          | Escola       |
+------------+----------+----------+--------------+
| 10/03/2017 | Escola   |          |              |
+------------+----------+----------+--------------+
| 01/05/2017 |          | Trabalho |              |
+------------+----------+----------+--------------+
| 03/05/2017 |          | Casa     |              |
+------------+----------+----------+--------------+
| 10/12/2017 |          |          | Trabalho     |
+------------+----------+----------+--------------+

See it working here on ideone.

  • Thanks for the answer, I’ll analyze to understand this code later.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.