Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Projeto] Resolução do Desafio #2

Olá, fiz a resolução do desafio 2 utilizando dicionário, achei que seria mais fácil e eficiente. No entanto, na prática tive um pouco de dificuldade em mostrar o nome do tom, e meu código parece que ficou um pouco maior que o da resolução. Analisando o meu código, há algo que eu fiz a mais, ou que pode ser simplificado, ainda utilizando dicionário?

Program.cs

LinqFilters.FiltrarMusicasPorTonalidade(musicas, 1); // 1 = C#

Musica.cs

 [JsonPropertyName("key")]
 public int Key { get; set; }

 private Dictionary<int, string> notas = new Dictionary<int, string>
 {
     { 0,  "C"  },
     { 1,  "C#" },
     { 2,  "D"  },
     { 3,  "D#" },
     { 4,  "E"  },
     { 5,  "F"  },
     { 6,  "F#" },
     { 7,  "G"  },
     { 8,  "G#" },
     { 9,  "A"  },
     { 10, "A#" },
     { 11, "B"  }
 };

 public string Nota
 {
     get
     {
         if (notas.TryGetValue(Key, out string? value))
         {
             return value;
         }
         else
         {
             return "Nota inválida";
         }
     }
 }

LinqFilters.cs

public static void FiltrarMusicasPorTonalidade(List<Musica> musicas, int nota)
{
    var tonalidade = musicas.Where(m => m.Key.Equals(nota)).Select(m => m.Nota).Distinct().ToList();
    var musicasTonalidade = musicas.Where(m => m.Key.Equals(nota)).OrderBy(m => m.Nome).ThenBy(m => m.Artista).Select(m => m.Nome).Distinct().ToList();

    Console.WriteLine($"Músicas da tonalidade {tonalidade[0]}:\n");
    foreach (var musica in musicasTonalidade)
    {
        Console.WriteLine($"- {musica}");
    }
    Console.WriteLine();
}
5 respostas

Olá, Izabela.

Tudo bem?

Muito orbigado por compartilhar a sua solução aqui com a gente. Que bom que você está se dedicando ao desafio! Utilizar dicionário realmente pode ser uma solução eficiente. Seu código para mapeamento das notas está bem estruturado e organizado.

Espero ter ajudado e bons estudos!

Bom, não respondeu minha pergunta kk

Verdade , acabei deixando só o feedback.

O seu código já está bastante organizado, mas sempre há espaço para pequenas melhorias. Vou dar algumas dicas:

  1. Tornar o dicionário notas estático: Como o dicionário de notas é o mesmo para todas as instâncias de Musica, você pode torná-lo estático para economizar memória.

  2. Filtragem e impressão de músicas: A filtragem e a obtenção da tonalidade podem ser feitas de maneira mais eficiente. Você pode combinar algumas operações LINQ para evitar a repetição de código.

Aqui está uma versão revisada do seu código:

Program.cs

LinqFilters.FiltrarMusicasPorTonalidade(musicas, 1); // 1 = C#

Musica.cs

public class Musica
{
    [JsonPropertyName("key")]
    public int Key { get; set; }

    private static readonly Dictionary<int, string> notas = new Dictionary<int, string>
    {
        { 0,  "C"  },
        { 1,  "C#" },
        { 2,  "D"  },
        { 3,  "D#" },
        { 4,  "E"  },
        { 5,  "F"  },
        { 6,  "F#" },
        { 7,  "G"  },
        { 8,  "G#" },
        { 9,  "A"  },
        { 10, "A#" },
        { 11, "B"  }
    };

    public string Nota => notas.TryGetValue(Key, out string? value) ? value : "Nota inválida";
}

LinqFilters.cs

public static class LinqFilters
{
    public static void FiltrarMusicasPorTonalidade(List<Musica> musicas, int nota)
    {
        var tonalidade = Musica.notas.TryGetValue(nota, out string? tonalidadeStr) ? tonalidadeStr : "Nota inválida";
        
        var musicasTonalidade = musicas
            .Where(m => m.Key == nota)
            .OrderBy(m => m.Nome)
            .ThenBy(m => m.Artista)
            .Select(m => m.Nome)
            .Distinct()
            .ToList();

        Console.WriteLine($"Músicas da tonalidade {tonalidade}:\n");
        foreach (var musica in musicasTonalidade)
        {
            Console.WriteLine($"- {musica}");
        }
        Console.WriteLine();
    }
}

Pontos Principais:

  1. Dicionário Estático: O dicionário de notas foi tornado estático para que haja apenas uma cópia em memória.
  2. Simplificação de LINQ: A filtragem e a obtenção da tonalidade foram combinadas para evitar duplicidade.

Essas alterações devem deixar seu código mais eficiente e fácil de manter. Se tiver mais alguma dúvida ou precisar de mais ajuda, sinta-se à vontade para perguntar!

  • Sobre o dicionário estático, agradeço mt pela dica!
  • Sobre a simplificação de LINQ, o método refeito que vc passou só funciona se eu alterar o nível do dicionário notas para public, mas isso seria correto?

Quero dizer, no meu código o dicionário era protected e no seu está como private, mas em nenhum dos casos ele funciona no seu método FiltrarMusicasPorTonalidade devido ao nível de privacidade. Explicando melhor, gostaria de saber se posso deixar o dicionário como public, ou se seria melhor criar uma property (se é que é possível).

solução!

Você está certa sobre a questão do nível de acesso. Você pode criar uma propriedade pública apenas para leitura que permita o acesso ao dicionário de maneira segura.

Aqui está a versão ajustada do código:

Program.cs

LinqFilters.FiltrarMusicasPorTonalidade(musicas, 1); // 1 = C#

Musica.cs

public class Musica
{
    [JsonPropertyName("key")]
    public int Key { get; set; }

    private static readonly Dictionary<int, string> notas = new Dictionary<int, string>
    {
        { 0,  "C"  },
        { 1,  "C#" },
        { 2,  "D"  },
        { 3,  "D#" },
        { 4,  "E"  },
        { 5,  "F"  },
        { 6,  "F#" },
        { 7,  "G"  },
        { 8,  "G#" },
        { 9,  "A"  },
        { 10, "A#" },
        { 11, "B"  }
    };

    public static IReadOnlyDictionary<int, string> Notas => notas;

    public string Nota => notas.TryGetValue(Key, out string? value) ? value : "Nota inválida";
}

LinqFilters.cs

public static class LinqFilters
{
    public static void FiltrarMusicasPorTonalidade(List<Musica> musicas, int nota)
    {
        var tonalidade = Musica.Notas.TryGetValue(nota, out string? tonalidadeStr) ? tonalidadeStr : "Nota inválida";
        
        var musicasTonalidade = musicas
            .Where(m => m.Key == nota)
            .OrderBy(m => m.Nome)
            .ThenBy(m => m.Artista)
            .Select(m => m.Nome)
            .Distinct()
            .ToList();

        Console.WriteLine($"Músicas da tonalidade {tonalidade}:\n");
        foreach (var musica in musicasTonalidade)
        {
            Console.WriteLine($"- {musica}");
        }
        Console.WriteLine();
    }
}
  1. Propriedade Pública Somente Leitura: A propriedade Notas foi criada para fornecer acesso ao dicionário de notas de forma segura.
  2. Encapsulamento: O dicionário continua privado, mas é acessível de forma controlada, evitando exposição desnecessária.

Com essa abordagem, você mantém o encapsulamento e a segurança dos dados, permitindo ao mesmo tempo o acesso necessário para a filtragem. Isso deve resolver sua dúvida.

Qualquer dúvida, conta com a gente. Bons estudos.