Tengo una pregunta con la que espero me puedan ayudar. Acabo de empezar con React Native y estoy trabajando en un generador de nombres simple.
Tengo una matriz con diferentes nombres en ella. Cuando hago clic en el botón, se genera un número aleatorio. Este número está asociado con la lista de nombres de la matriz.
Todo esto funciona, pero obtengo nombres duplicados. Me gustaría revisar toda la lista sin que haya un nombre duplicado. Cuando se han pasado todos los nombres, la lista comienza de nuevo.
Estaba pensando en hacer una matriz separada que lleve un registro de los números que han pasado. Y luego excluye esos números. Pero no estoy seguro de cómo agregar esto y si esta es la forma correcta.
Vea a continuación mi código. Disculpas si esto es un poco desordenado o engorroso.
import React, { useState } from "react"; import { StyleSheet, Text, View, Button } from "react-native"; export default function GirlScreen() { const RandomNumber = (min, max) => { return Math.floor(Math.random() * (max - min + 1) + min); }; const [count, setCount] = useState(0); const onPress = () => { setCount(RandomNumber(1, 100)); }; const random = RandomNumber(1, 5); var differentNames = { namesContainer: { names: [ { name: "(1) Sophie", id: 1 }, { name: "(2) Emma", id: 2 }, { name: "(3) Lisa", id: 3 }, { name: "(4) Esmée", id: 4 }, { name: "(5) Zoe", id: 5 }, ], }, }; function findLinkByName(random) { for (const item of differentNames.namesContainer.names) { if (item.id === random) { return item.name; } } } return ( <View style={styles.countContainer}> <Text style={styles.name}>{findLinkByName(random)}</Text> <Button onPress={onPress} title="Next Name" /> </View> ); } const styles = StyleSheet.create({ countContainer: { flex: 1, alignItems: "center", justifyContent: "center", }, name: { color: "black", fontSize: 30, }, });si entiendo que quieres seleccionar sin retorno
let arr1 = ['a', 'b', 'c']; let value;Opción 1: copiar la matriz a la matriz temporal
let arr2 = [...arr1]; let random_index = Math.floor(Math.random() * arr2.length); value = arr2[random_index]; arr2 = arr2.filter((val, index) => index !== random_index); if (arr2.length === 0) arr2 = [...arr1];Opción 2: Guardar los índices de la matriz
let arr2 = Array.from(Array(arr1.length).keys()); let random_index = Math.floor(Math.random() * arr2.length); value = arr1[arr2[random_index]]; arr2 = arr2.filter((val, index) => index !== random_index); if (arr2.length === 0) arr2 = Array.from(Array(arr1.length).keys());Opción 1: Rápido y Fácil
Cree un objeto en el estado para realizar un seguimiento de los ID de nombre utilizados.
const [usedIds, setUsedIds] = useState([]);Luego actualice la función findLinkByName para usar esta matriz. También debe invocar el generador de números aleatorios dentro de la función.
function findLinkByName() { // clear array if full if(usedIds.length === differentNames.namesContainer.names.length) { setUsedIds([]); } // find unique ID let randomId; do { randomId = RandomNumber(1,5); } while(usedIds.includes(randomId)); // add used ID to array setUsedIds(prev => [...prev, randomId]); // return random name return differentNames.namesContainer.names.find(n => n.id === randomId); }Opción 2: Mover nombres a estado
También puede simplemente agregar una propiedad used a cada objeto de nombre en el contenedor de nombre y cambiarlo para que se almacene en estado para que podamos mutarlo. La parte más fea de esto es que los nombres se mantienen 3 niveles de profundidad en el objeto. Si eso se puede levantar, entonces las siguientes declaraciones podrían ser mucho más cortas.
const [names, setNames] = useState({ namesContainer: { names: [ { name: "(1) Sophie", id: 1, used: false }, { name: "(2) Emma", id: 2, used: false }, { name: "(3) Lisa", id: 3, used: false }, { name: "(4) Esmée", id: 4, used: false }, { name: "(5) Zoe", id: 5, used: false }, ], }, }); También recomendaría usar const y let var por varias razones 😉
Luego, su función findLinkByName se puede actualizar para que funcione de manera mucho más eficiente de esta manera:
function findLinkByName() { // clear array if full if(names.namesContainer.names.filter(n => !n.used).length === 0) { let newNames = {...names}; newNames.namesContainer.names.map(n => {...n, used: false}); setNames(newNames); } // find random ID const unusedNames = names.filter(n => !n.unsed); const randId = Math.floor(Math.random() * unusedNames.length); // update state let newNames = {...names}; newNames.namesContainer.names.map(n => { return (n.id === randId) ? {...n, used: true} : {...n} }); setNames(newNames); // return random name return names.namesContainer.names.find(n => n.id === randId); }Podría realizar un seguimiento de dos estados. Uno tiene los nombres ya selectedNames y el otro todavía tiene los nombres availableNames de la siguiente manera.
const [selectedNames, setSelectedNames] = useState([]) const [availableNames, setAvailableNames] = useState([ { name: "(1) Sophie", id: 1 }, { name: "(2) Emma", id: 2 }, { name: "(3) Lisa", id: 3 }, { name: "(4) Esmée", id: 4 }, { name: "(5) Zoe", id: 5 }, ]) Luego, elegimos un número aleatorio entre 0 y la longitud de avialableNames que representa el índice que queremos elegir de avialableNames .
const random = RandomNumber(0, availableNames.length - 1); Entonces, su función onPress se ve de la siguiente manera.
const onPress = () => { setAvailableNames(availableNames.filter(n => n !== availableNames[random])) setSelectedNames([...selectedNames, availableNames[random]]) }; Agregamos el nuevo nombre elegido al azar a los nombres selectedNames y lo eliminamos de los nombres availableNames al mismo tiempo.
Su función findLinkByName podría tener el siguiente aspecto.
function findLinkByName(random) { if (availableNames.length === 0) { setAvailableNames(selectedNames.sort((a, b) => a.id - b.id)) setSelectedNames([]) return availableNames[0] } return availableNames[random].name } Mientras haya nombres en availableNames , es decir, su longitud no es igual a 0 , simplemente lo seleccionamos y devolvemos su nombre. Si se han seleccionado todos los nombres disponibles, restablecemos los estados, ordenamos los nombres seleccionados por su id prop y devolvemos el primer nombre de la lista nuevamente.
Aquí hay un refrigerio de trabajo.