Losowanie obiektów bez powtórzeń i dodawanie ich do tablicy

0

Dobry wieczór,

mam tablicę z obiektami :

const listContainer=[ ];
const list = [
{
id:1,
name:A
},
{
id:2,
name:B
},
...
{
id:11,
name:K
}

Chciałbym wylosować 6 obiektów bez powtórzeń, w kodzie mam tak:

for(let i=0; i<6; i++){
let randomList = list.splice(Math.floor(Math.random()*list.length,1)
listContainer.push(randomList)
}

Na końcu chciałbym dodać te 6 losowych obiektów do DOM i tu niestety mam problem, dodaje się tylko jeden obiekt

listContainer.forEach((item,idx)=>{
 const listDiv = document.createElement('div')
        <div class="list-info">
         <span id="name">${item[idx].name}</span>
         <span id="id">${item[idx].id}</span>
        </div>`
        randomListContainer.appendChild(listDiv)
1
Falra napisał(a):

listContainer.forEach((item,idx)=>{
const listDiv = document.createElement('div')


${item[idx].name}
${item[idx].id}
`
randomListContainer.appendChild(listDiv)</p>

W tym miejscu jest coś źle sformatowane/skopiowane, albo po prostu błąd :) Tworzysz kod HTML, ale nigdzie go nie przypisujesz.

listContainer.forEach((item,idx)=>{
  const listDiv = document.createElement('div');
  listDiv.outerHTML = `
     <div class="list-info">
        <span id="name">${item[idx].name}</span>
        <span id="id">${item[idx].id}</span>
     </div>
  `;
 
  randomListContainer.appendChild(listDiv);
});
3
Xarviel napisał(a):
listContainer.forEach((item,idx)=>{
  const listDiv = document.createElement('div');
  listDiv.outerHTML = `
     <div class="list-info">
        <span id="name">${item[idx].name}</span>
        <span id="id">${item[idx].id}</span>
     </div>
  `;
 
  randomListContainer.appendChild(listDiv);
});

Jezus maria, a XSS? -.-

Nie wierze ile jest amatorów tutaj. Do społeczności! Proszę nie używać kodu wyżej.

Poprawiona wersja:

  listDiv.outerHTML = `
     <div class="list-info">
        <span id="name">${encode(item[idx].name)}</span>
        <span id="id">${encode(item[idx].id)}</span>
     </div>
  `;

Przykładowa implementacja encode(),

function encode(text) {
  var element = document.createElement('p');
  element.innerText = text;
  return element.innerHTML;
}
1
TomRiddle napisał(a):

Jezus maria

oraz Ty panie Boże miejcie nas w swojej opiece i chroncie nas przed wszelkim złem :]

TomRiddle napisał(a):

a XSS? -.-

Jeśli nie pobiera danych od użytkownika to raczej o XSS nie musi się martwić.

2
Xarviel napisał(a):

Jeśli nie pobiera danych od użytkownika to raczej o XSS nie musi się martwić.

Bzdura.

Wystarczy żeby zaenkodował stringa, kiedy łączy go ze stringiem. Poza tym, nie musi wsadzić tam nic od usera, żeby zepsuć widok, wystarczy że jakiś name będzie miał w sobie &, >, < albo "`" i już widok wykrzaczony.

0

Dziękuje za pomoc, ale niestety ciągle nie jestem w stanie rozwiązać swojego problemu. Dalej funkcja tworzy jeden obiekt, a nie wszystkie wylosowane 6.

0
Falra napisał(a):

Dziękuje za pomoc, ale niestety ciągle nie jestem w stanie rozwiązać swojego problemu. Dalej funkcja tworzy jeden obiekt, a nie wszystkie wylosowane 6.

Pokaż cały kod jaki masz.

0

Proszę, moim celem jest żeby konsola wypisywała 6 losowych obiektów

let listContainer = [];
const list = [
{
id:1,
name:'A'
},
{
id:2,
name:'B'
},
{
id:3,
name:'C'
},
{
id:4,
name:'D'
},
{
id:5,
name:'E'
},
{
id:6,
name:'F'
},
{
id:7,
name:'G'
},
{
id:8,
name:'H'
},
{
id:9,
name:'I'
},
{
id:10,
name:'J'
},
{
id:11,
name:'K'
},
{
id:12,
name:'L'
},];
function randomList(){
        for(let i=0; i<6; i++){
        let randomList = list.splice(Math.floor(Math.random()*list.length,1));
        listContainer.push(randomList)}
}
function showList(){
    randomList()
    for(i=0; i<listContainer.length; i++){
    listContainer.forEach((item,idx)=>{
       console.log(item[idx].name, idx)
      });
    }
}
showList()
1

Myślę że Twoim pierwszym problemem jest

listContainer.forEach

a drugim

(item,idx)=>{
       console.log(item[idx].name, idx)
      });

Moim zdaniem powinno być:

listContainer[i].forEach

oraz

(item,idx)=>{
       console.log(item.name, idx)
      });

A co do samej implementacji, to tak:

  1. Nie używaj zmiennych globalnych. Przekazuj wartości do funkcji za pomocą argumentów, i zwracaj je za pomocą return. Nie edytuj zmiennych "w miejscu".
  2. Mógłbyś użyć .forEach() zamiast zwykłego for.
  3. Słyszałeś może o flatMap()? Myślę że mogłoby Ci się przydać: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap

Przykład poprawionego kodu, moim zdaniem:

function randomList(elements, amount) {
  const container = [];
  for (let i = 0; i < amount; i++) {
    const randomList = elements.splice(Math.floor(Math.random() * elements.length));
    container.push(randomList)
  }
  return container;
}

function showList(items, amount) {
  const listContainer = randomList(items, amount);
  listContainer.forEach(list => {
    list.forEach((item, idx) => {
      console.log(item.name, idx)
    });
  });
}

showList(list, 6);

PS: @Falra W jakim środowisku uruchamiasz ten kod? Ponieważ kiedy ja go uruchomiłem, to od razu dostałem wyjątek, i na 99.99% Ty też go dostałeś, tylko go nie widziałeś. Jeśli uruchamiasz kod w przeglądarce, to upewnij się że masz otworzone narzędzia developerskie z otwartą zakładką "Console", tam będzie widać wyjątki rzucane przez kod, pomogą Ci.

0

@TomRiddle: Dziękuje, to co wysłałeś jest dla mnie bardzo pomocne. Mam jeszcze jedno pytanie, dlaczego w tym momencie konsola wypisuje wszystkie obiekty a nie tylko 6 wylosowanych?

0
Falra napisał(a):

@TomRiddle: Dziękuje, to co wysłałeś jest dla mnie bardzo pomocne. Mam jeszcze jedno pytanie, dlaczego w tym momencie konsola wypisuje wszystkie obiekty a nie tylko 6 wylosowanych?

Wklej proszę kod którego używasz

0

@TomRiddle:proszę

let listContainer = [];
const list = [
{
id:1,
name:'A'
},
{
id:2,
name:'B'
},
{
id:3,
name:'C'
},
{
id:4,
name:'D'
},
{
id:5,
name:'E'
},
{
id:6,
name:'F'
},
{
id:7,
name:'G'
},
{
id:8,
name:'H'
},
{
id:9,
name:'I'
},
{
id:10,
name:'J'
},
{
id:11,
name:'K'
},
{
id:12,
name:'L'
},];

function randomList(elements, amount) {
    const container = [];
    for (let i = 0; i < amount; i++) {
      const randomList = elements.splice(Math.floor(Math.random() * elements.length));
      container.push(randomList)
    }
    return container;
  }
  
  function showList(items, amount) {
    const listContainer = randomList(items, amount);
    listContainer.forEach(list => {
      list.forEach((item, idx) => {
        console.log(item.name, idx)
      });
    });
  }
  
  showList(list, 6);
0
Falra napisał(a):

@TomRiddle: Dziękuje, to co wysłałeś jest dla mnie bardzo pomocne. Mam jeszcze jedno pytanie, dlaczego w tym momencie konsola wypisuje wszystkie obiekty a nie tylko 6 wylosowanych?

No więc patrząc na Twój kod, widzę dwa problemy.

  • Pierwszy, masz zupełny problem z debugowaniem swoich aplikacji. Jeśli chciałbyś spróbować naprawić swój kod, i dostrzec gdzie zrobiłeś błąd, powinienś dodać console.log() zaraz po wyjśćiu z funkcji randomItems():
    const listContainer = randomList(items, amount);
    console.log(listContainer);
    
    Zobaczyłbyś wtedy, że ile razy uruchomisz swoją aplikację, to dostaniesz różną ilość elementów. Sugeruje to że Twój call do .splice() zwraca randomową ilość elementów, zamiast jednego. Prawdopodobnie wołasz splice() z początkowym indexem, i zwraca wartości do końca. Powinieneś dodać 1 jako drugi argument splice(), żeby dostać tylko pierwszy element.
  • const randomList = elements.splice(Math.floor(Math.random() * elements.length), 1);
    
  • Po drugie, skoro chcesz tylko jeden element, to nie ma powodu żeby zwracać array, zamiat pojedynczego elementu.

Tu jest poprawka

const list = [
  {id: 1, name: 'A'},
  {id: 2, name: 'B'},
  {id: 3, name: 'C'},
  {id: 4, name: 'D'},
  {id: 5, name: 'E'},
  {id: 6, name: 'F'},
  {id: 7, name: 'G'},
  {id: 8, name: 'H'},
  {id: 9, name: 'I'},
  {id: 10, name: 'J'},
  {id: 11, name: 'K'},
  {id: 12, name: 'L'},
];

function randomList(elements, amount) {
  const result = [];
  for (let i = 0; i < amount; i++) {
    const [element] = elements.splice(Math.floor(Math.random() * elements.length), 1);
    result.push(element)
  }
  return result;
}

randomList(list, 6).forEach((item, idx) => console.log(item.name, idx));
0

@TomRiddle: Dziękuje, a dlaczego w tym przypadku wywołanie funkcji zwraca błąd, że items nie jest zdefiniowane?

0
Falra napisał(a):

@TomRiddle: Dziękuje, a dlaczego w tym przypadku wywołanie funkcji zwraca błąd, że items nie jest zdefiniowane?

Bo items jest niezdefiniowe ;D

Zrobiłem błąd, poprawiłem post już wyżej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1