.NET Framework Developer Center > Fóruns do .NET Development > .NET Development - Geral > Criando Indexações extras para uma coleção
Fazer uma PerguntaFazer uma Pergunta
 

RespondidoCriando Indexações extras para uma coleção

  • quarta-feira, 21 de outubro de 2009 16:33LeandrodeMelloFagundes Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Boa tarde pessoal. Criei uma classe que é herda de um Collectionbase.

    Dentro desta classe, criei duas Listas. Uma lista de ID e uma Lista de nomes.
    Dei um override nos métodos, add, clear, set e remove para quando uma dessas operações for executada, alterar o valor destas listas internas.
    Ou seja, no protected override void OnInsertComplet eu pego o valor inserido e insiro seu ID na list de ID e insiro seu NOME na lista de nome.
    Até ai tudo bem, quando queria um objeto pelo nome, minha propriedade Item pegava o IndexOF(nome) e com esse indexof pegava na base.List o objeto real. Deu pra entender o processo?

    Porém, identifiquei aqui que ao alterar em outro ponto do código o nome do meu objeto, apenas a coleção base sofreu alteração. A coleção de nome continua contendo o nome antigo. Se eu procurar pelo novo nome não encontra nada.

    Existe alguma forma de fazer isso ou de implementar melhor isso que quero?

    Att
    Leandro
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)

Respostas

  • sábado, 31 de outubro de 2009 2:36Filipe Assis Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Respondido
    Leandro,

    Você pode criar a classe sem essas sub-coleções, e adicionar o método Item a ela. Esse método utilizaria o método Find da classe List passando uma delegate que retorna quando existe uma pessoa com o nome especificado. Você também poderia usar o método FindAll, caso a sua lista possa ter nomes repetidos.... Segue como ficaria a classe:

    public class ColecaoPessoa : List<Pessoa>
    {
        public Pessoa Item(String nome)
        {
            return base.Find(delegate(Pessoa p) { return p.Nome == nome; });
        }
    }

    Espero ter ajudado.

    Abraço!

Todas as Respostas

  • sexta-feira, 30 de outubro de 2009 18:52Filipe Assis Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Ola Leandro,

    Tem como você colocar o código da classe aqui?

    Abs
  • sexta-feira, 30 de outubro de 2009 19:24LeandrodeMelloFagundes Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém Código
    Qualquer uma Filipe.

    Ex:

        public class ColecaoPessoa : List<Pessoa>
        {
            private List<string> _colecaoIndexadaPorNome;
            private List<int> _colecaoIndexadaPorIdade;
    
    
            private void Add(Pessoa pessoa) 
            {
                _colecaoIndexadaPorIdade.Add(pessoa.Idade);
                _colecaoIndexadaPorNome.Add(pessoa.Nome);
                base.Add(pessoa);
            }
        }
    
    O que eu gostaria de fazer ali?
    Eu teria 2 sub-coleções que me ajudariam com indices (aumentando a performance)

    Poderia ter um ColecaoPessoa.Item(NomePessoa) onde a propriedade item que recebe uma string (nomepessoa) ia executar um Me.Item(_colecaoIndexadaPorNome.indexof(NomePessoa));

    dessa forma, eu pego o indice que aquele nome foi inserido na coleção (por exemplo, o nome Filipe está na posição 15. o IndexOf na colecaoIndexadaPorNome.IndexOf("Felipe") ia retornar 15) e passo por parâmetro pra Me.Item(Index) que precisa da posição. Consigo o Objeto que está localizado na posição 15 sem precisar varrer a lista inteira.

    isso é muito util e inteligente, até o momento em que por algum motivo, o nome Filipe, muda para FELIPE por exemplo. Ai na sublista, o nome FELIPE não existe, e o nome FILIPE está na 15 posição. Já vai dar errado



    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
  • sábado, 31 de outubro de 2009 2:36Filipe Assis Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Respondido
    Leandro,

    Você pode criar a classe sem essas sub-coleções, e adicionar o método Item a ela. Esse método utilizaria o método Find da classe List passando uma delegate que retorna quando existe uma pessoa com o nome especificado. Você também poderia usar o método FindAll, caso a sua lista possa ter nomes repetidos.... Segue como ficaria a classe:

    public class ColecaoPessoa : List<Pessoa>
    {
        public Pessoa Item(String nome)
        {
            return base.Find(delegate(Pessoa p) { return p.Nome == nome; });
        }
    }

    Espero ter ajudado.

    Abraço!
  • sábado, 31 de outubro de 2009 3:03LeandrodeMelloFagundes Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Filipe,

    a idéia é boa. Você sabe se existe realmente um ganho de performance neste método? Já fez testes com isso?
    Gostaria de saber pois performance é algo que teremos real necessidade em alcançar os melhores resultados.

    Desde já, muito grato.

    Att
    Leandro
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
  • sábado, 31 de outubro de 2009 4:51Filipe Assis Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Leandro,

    Eu nunca fiz testes não, mas em alguns pontos podemos analisar sem os testes (veja se concorda comigo):

    - Ele aloca menos memória, pois são 2 listas a menos que serão instanciadas.
    - Ao manipular os elementos da lista (adicionar, remover) menos processamento é usado, pois não é necessário incluir em outras listas.
    - O ponto que pode gerar uma dúvida é no método "ColecaoPessoa.Item", pois na sua abordagem ele faz uma busca numa lista de string (do primeiro ao último elemento), e depois acessa a lista de pessoas diretamente pelo índice (mas é necessário verificar se o índice é negativo). Já no meu ele faz a busca diretamente na lista de Pessoas (também do primeiro ao último), ou seja, ele itera sobre objetos do tipo Pessoa, e acessa seus nomes para então fazer a comparação, mas, em contrapartida, não é necessário fazer qualquer tipo de verificação de índice. Aí fica a dúvida... Mesmo assim meu palpite é que trabalhar com outras listas seria mais custoso.

    Mas Leandro, nós estamos falando aqui de diferenças muito pequenas de performance. A sua aplicação é crítica a esse ponto?

    Ps: Se você fizer esse teste, informe o resultado por favor!

    Abraço!
    Filipe Assis
  • terça-feira, 3 de novembro de 2009 13:22LeandrodeMelloFagundes Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     
    Muito boa Filipe.

    Fiz alguns testes baseando na performance do Find e de ter uma sublista. Ambos funcionaram muito bem, e a diferença da sublista e do find em relação a performance é 0150 milisegundos. Menos de 1 milisegundo.
    Não vou nem considerar essa diferença, pois nunca sabemos como está o processador naquele exato momento. Então realmente, o find consegue obter um resultado ótimo.
    Obrigado pela ajuda!
    :)

    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)