Last active
January 19, 2023 19:34
-
-
Save rponte/70ec0a7c109bb58121f246dd1372154d to your computer and use it in GitHub Desktop.
Algoritimos: Encontrar menor lance (valor) único em uma lista
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- drop a cria tabela | |
-- | |
drop table tb_lances; | |
create table tb_lances (VALOR number not null); | |
-- | |
-- limpa e popula tabela | |
-- | |
delete from tb_lances; | |
insert all | |
into tb_lances values (10) | |
into tb_lances values (30) | |
into tb_lances values (20) -- menor lance unico | |
into tb_lances values (10) | |
select * from dual | |
; | |
-- | |
-- logica em uma query | |
-- | |
select min(valor) as menor_lance_unico | |
from ( | |
select l.* | |
,count(*) as total | |
from tb_lances l | |
group by l.valor | |
having count(*) = 1 | |
order by l.valor asc -- obs: desnecessario! :-) | |
) | |
; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static java.util.Comparator.naturalOrder; | |
import static java.util.function.Function.identity; | |
import static java.util.stream.Collectors.counting; | |
import static java.util.stream.Collectors.groupingBy; | |
import java.util.stream.Collectors; | |
import java.util.stream.Comparator; | |
import java.util.*; | |
public class Sorteio { | |
/** | |
* Solução simples com a API Collections do Java (nada de Guava, Commons-Collections etc) | |
*/ | |
public Integer sorteia(List<Integer> lances) { | |
SortedSet<Integer> unicos = new TreeSet<>(); // mantem ordem natural | |
Set<Integer> duplicados = new HashSet<>(); | |
for (Integer lance : lances) { | |
if (!unicos.add(lance)) { | |
duplicados.add(lance); | |
} | |
} | |
unicos.removeAll(duplicados); // remove TODOS os duplicados | |
return unicos.first(); // retorna o primeiro | |
} | |
/** | |
* Solução quando não se tem muito conhecimento da API Collections do Java | |
*/ | |
public int sorteia2(List<Integer> lances) { | |
// agrupamos por valor | |
Map<Integer, Integer> lancesPorValor = new HashMap<>(); | |
for (Integer lance : lances) { | |
if (!lancesPorValor.containsKey(lance)) { | |
lancesPorValor.put(lance, 0); | |
} | |
int total = lancesPorValor.get(lance); | |
lancesPorValor.put(lance, ++total); | |
} | |
// identificamos e selecionamos os lances unicos | |
List<Integer> unicos = new ArrayList<>(); | |
for (Entry<Integer, Integer> entry : lancesPorValor.entrySet()) { | |
if (entry.getValue() == 1) { | |
unicos.add(entry.getKey()); | |
} | |
} | |
// ordenamos lances por ordem crescente | |
Collections.sort(unicos); | |
// pegamos o 1o item, ou seja, o menor | |
return unicos.get(0); | |
// ou usando min() | |
// return Collections.min(unicos); | |
} | |
/** | |
* Usando API de Streams do Java 8 | |
*/ | |
public Integer sorteiaComJava8(List<Integer> lances) { | |
Integer lance = lances.stream() | |
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting())) // agrupa e conta | |
.entrySet() | |
.stream() | |
.filter(e -> e.getValue() == 1) // elimina os repetidos | |
.map(e -> e.getKey()) | |
.min(Comparator.comparingInt(Integer::intValue)) // min() ou sorting+first | |
.orElse(null) | |
; | |
return lance; | |
} | |
/** | |
* Usando API de Streams do Java 8 de forma mais clean | |
*/ | |
public Integer sorteiaComJava8_clean(List<Integer> lances) { | |
Integer lance = lances.stream() | |
.collect(groupingBy(identity(), counting())) // agrupa e conta | |
.entrySet() | |
.stream() | |
.filter(e -> e.getValue() == 1) // elimina os repetidos | |
.map(Map.Entry::getKey) | |
.min(naturalOrder()) // min() ou sorting+first | |
.orElse(null) | |
; | |
return lance; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.Assert.assertEquals; | |
import java.util.Arrays; | |
import java.util.List; | |
import org.junit.Test; | |
public class SorteioTest { | |
@Test | |
public void deveEncontrarOMenorLanceUnico() { | |
List<Integer> lances = Arrays.asList(1, 2, 2, 3, 4, 1, 5, 6, 7, 8, 6, 7, 3, 9); | |
Sorteio sorteio = new Sorteio(); | |
Integer valor = sorteio.sorteia(lances); | |
assertEquals("menor valor unico", 4, valor.intValue()); | |
} | |
@Test | |
public void naoDeveEncontrarOMenorLanceUnico_quandoNaoHouverLances() { | |
// cenario | |
List<Integer> lances = Arrays.asList(); | |
// ação | |
Sorteio fordKa = new Sorteio(); | |
Integer menorLanceUnico = fordKa.sorteiaComJava8(lances); | |
// validação | |
assertEquals(null, menorLanceUnico); | |
} | |
} |
Como ficaria em C#:
return list
.GroupBy (x => x)
.Where(x => x.Count() == 1)
.Min(x => x.Key);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Que saudade do LINQ. Ficaria bem melhor que isso: