Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Implementando el método Get

10/25
Recursos

Aportes 150

Preguntas 11

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

De forma grafica como se llega a cada elemento dentro de los buckets, y del currentBucket, a que arreglo de arreglos de clave, valor:

Saludos 😃

👩‍💻👨‍💻 Código de la clase y solución al reto de Remove y getAllKeys

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }

  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1];
        }
      }
    }
    return undefined;
  }

  getAllKeys() {
    const keys = [];
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i]) {
        for (let j = 0; j < this.data[i].length; j++) {
          keys.push(this.data[i][j][0]);
        }
      }
    }
    return keys;
  }

  remove(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          const deletedValue = this.data[address][i];
          this.data[address].splice(i, 1);
          return deletedValue;
        }
      }
    }
    return undefined;
  }
}

Creo que ha llegado el momento que rehagan TODOS los cursos de Javascript y que los haga Diego, este es su curso más complejo sobre Javascript que ha enseñado y sin embargo se entiende todo, hasta había entendido la lógica del matriz de arrays antes de que lo explique con el [ [], [], …] y eso que yo no suelo entender a la primera…

 getKeys() {
    return this.data.reduce((instance, value) => {
      const keys = value.map(([key]) => key);
      return instance.concat(keys)
    }, []);
  }

Dejo el código del delete (Es prácticamente lo mismo que el get, pero en esta ocasión lo elimina con delete), le puse remove para que el linter de JS no me diera problemas ^^

remove(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    const element = currentBucket[i][1];
                    delete currentBucket[i][1];
                    return element;
                }
            }
        }
        return undefined;
    }

Hay un detalle con la función de set, es que si haces dos veces un set de la misma llave entonces sólo lo vas a añadir al arreglo y cuando trates de hacer un get te devuelve el primer valor y nunca los que se añadieron de manera posterior, estuve viendo que en la implementación de Hash Table que tiene Java lo que hacen es sobreescribir el valor de la llave con el nuevo, más info al respecto acá. Para emular este comportamiento cambié un poco el método, y quedó así:

      set(key, value) {
        const address = this.hashMethod(key);
        if (!this.data[address]) {
          this.data[address] = [];
        }
        if (this.data[address].find((element) => element[0] === key)) {
          for (let i = 0; i < this.data[address].length; i += 1) {
            if (this.data[address][i][0] === key) {
              this.data[address][i][1] = value;
            }
          }
        } else {
          this.data[address].push([key, value]);
        }
        return this.data;
      }

También les comparto mis notas sobre éste módulo acá 😁.

mm no veo aun el potencial de este curso, veo muchas cosas repetidas de otros

My solucion para el metodo getKeys y delete

/* eslint-disable no-restricted-syntax */
/* eslint-disable no-plusplus */
class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }

  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }

  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          const value = currentBucket[i];
          currentBucket.splice(i, 1);
          return value;
        }
      }
    }
    return undefined;
  }

  keys() {
    const keys = [];
    this.data.forEach((bucket) => {
      bucket.forEach((keyPairValues) => {
        keys.push(keyPairValues[0]);
      });
    });
    return keys;
  }

  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }

  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) { return currentBucket[i][1]; }
      }
    }
    return undefined;
  }
}

const myHashTable = new HashTable(50);
myHashTable.set('franz', 1997);
myHashTable.set('laura', 1998);
myHashTable.set('mama', 1966);
myHashTable.set('elena', 2000);
myHashTable.get('franz');
myHashTable.keys();
myHashTable.delete('mama');
myHashTable.keys();

// RECIBE LA LLAVE QUE BUSCAMOS CON SU VALOR
    get(key){

        // LLAMAMOS LA FUNCION QUE NOS DEVUELVE UN HASH
        const address = this.hashMethod(key)

        // EL ADDRESS EN DONDE SE ENCUENTRA LA INFORMACIÓN
        const currentBucket = this.data[address]

        // SI ES TRUSTY 
        if( currentBucket )
        {
            // DESDE 0 HASTA EL LARGO DE EL CURRENT BUCKET
            for( let i = 0 ; i < currentBucket.length; i++ ) {

                // SI LA POSICION 0 DE EL ARREGLO ES IGUAL EL 
                // KEY QUE NOS PASARON
                if( currentBucket[i][0] === key) 
                {
                    // DEVOLVEMOS LA POSICION 1 QUE APUNTA A SU VALOR
                    return currentBucket[i][1]
                }
            }

        }
        // DEVOLVEMOS UNDEFINED
        return undefined

 }
<h3>Resuelto el reto 😁</h3>

Añadí un método findPair a la clase y lo que hace es abstraer la lógica de búqueda del método get, para poder usarla a la vez en el método de delete, y no repetir código.
Y para aplicar la lógica de si buscar un value o eliminar, recibe un callback como segundo parámetro que inyecta el valor del currentBucket y del index actual

class HashTable {
	constructor(size) {
		this.data = new Array(size);
	}

	hashMethod(key) {
		let hash = 0;

		for (let i = 0; i < key.length; i++) {
			hash = (hash + key.charCodeAt(i) * i) % this.data.length;
		}
		return hash;
	}

	set(key, value) {
		const address = this.hashMethod(key);

		if (!this.data[address]) {
			this.data[address] = [];
		}
		this.data[address].push([key, value]);

		return this.data;
	}

	get(key) {
		return this.findPair(key, (currentBucket, index) => currentBucket[index][1]);
	}

	getAllKeys() {
		const allKeys = [];

		this.data.forEach((bucket) => {
			for (let i = 0; i < bucket.length; i++) {
				allKeys.push(bucket[i][0]);
			}
		})

		return allKeys;
	}

	delete(key) {
		return this.findPair(key, (currentBucket, index) => {
			const pair = currentBucket[index];
			currentBucket.splice(index, 1);
			return pair;
		})
	}

	findPair(key, callback) {
		const address = this.hashMethod(key);
		const currentBucket = this.data[address];

		if (currentBucket) {
			for (let i = 0; i < currentBucket.length; i++) {
				if (currentBucket[i][0] === key) {
					return callback(currentBucket, i);
				}
			}
		}

		return undefined;
	}
}

const myHashTable = new HashTable(50);

myHashTable.set('Diego', 1990);

myHashTable.set("Mariana", 1998);

myHashTable.set("Alejandra", 2000);

Esta es mi propuesta al método para obtener todas las keys de una hastable.

  getKeys() {
    let keys = [];
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i]) {
        for (let j = 0; j < this.data[i].length; j++) {
          keys.push(this.data[i][j][0]);
        }
      }
    }
    return keys;
  }

Agradeceria su feedback

Les comparto la forma en que lo hice jaja, y suerte 😄

class HashTable {
    constructor(size){
        this.data = new Array(size);
    }

    hashMethod(key){
        let hash = 0;
        for (let i = 0; i < key; i++){
            hash = (hash + key.chartCodeAt(i) * i ) % this.data.length;
        }
        return hash;
    }

    set(key, value){
        const address = this.hashMethod(key);
        if(!this.data[address]){
            this.data[address] = [];
        }

        this.data[address].push([key, value]);

        return this.data;
    }

    get(key){
        const currentBucket = this.getCurrentBucket(key);
        if(currentBucket){
            for(let i = 0; i < currentBucket.length; i++){
                if(currentBucket[i][0] === key){
                    return currentBucket[i][1];
                }
            }
        }
        return undefined;
    }

    delete(key){
        const currentBucket = this.getCurrentBucket(key);
        let item;
        if(currentBucket){
            for(let i = 0; i < currentBucket.length; i++){
                if(currentBucket[i][0] === key){
                    item = currentBucket[i];
                    this.data[address] = currentBucket.filter(j => j[0] !== key);
                }
            }
        }
        return item || undefined;

    }

    getKeys(){
        const address = this.hashMethod();
        const currentBucket = this.data[address];
        return currentBucket.map(i => i[0]);
    }

    getValues(){
        const address = this.hashMethod();
        const currentBucket = this.data[address];
        return currentBucket.map(i => i[1]);
    }

    getAll(){
        return this.getCurrentBucket().map(i => ({ key:i[0], value: i[1] }));
    }

    find(value){
        const result = this.getCurrentBucket().filter(i => i[1] === value).map(i => ({
            key:i[0], value: i[1]
        }))
        return result.length > 1 ? result : result[0] || undefined;
    }

    getCurrentBucket(key){
        let address = key ? 
                        this.hashMethod(key) 
                        : this.hashMethod();
        return this.data[address];
    }
}

const myHashTable = new HashTable(50);

Les comparto mi solución al reto:

delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    for (let i = 0; i < currentBucket.length; i++) {
      if (currentBucket[i][0] === key) {
        const deleted = currentBucket[i][1];
        this.data[address].splice(i, 1);
        return deleted;
      }
    }
    return undefined;
}

getKeys() {
    let keys = [];
    for (let address of this.data) {
      if (!address) {
        continue;
      }
      for (let [key, value] of address) {
        keys.push(key);
      }
    }
    return keys;
}

Mi aporte a continuación

delete(key){
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if( currentBucket){
            for(let i = 0 ; i < currentBucket.length ; i++){
                if(currentBucket[i][0] === key){
                    delete this.data[address];
                    return currentBucket[i];
                }
            }
        }
        return undefined `The key: ${key}, doesn't exist!`;
    }
returnAllKeys(){
        const keys = [];
        for (let i = 0 ; i < this.data.length ;  i++){
            if(this.data[i]){
                for( let j = 0 ; j < this.data[i].length; j++){
                    keys.push(this.data[i][j][0]);
                }
            }
        }
        return keys;```

Dejo un ejemplo implementado en TypeScript con todos los métodos

En mi caso en el set compruebo si existe el elemento y en caso de que exista sobrescribo el valor, puesto que como lo hace el profesor si el key se repite tendrás varios con el mismo key lo cual no sirve de nada porque luego no podrás acceder a ellos. Haciéndolo de esta manera conseguimos un método con Idempotencia.

const util = require('util');

export class HashTable<K extends string, V> {
  private _length = 0;
  private readonly data: Array<[K, V][]>;
  private readonly size: number;

  constructor(size: number) {
    this.size = size;
    this.data = new Array(size);
  }

  private hash(key: string): number {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash += key.charCodeAt(i);
    }
    return hash % this.size;
  }

  set(key: K, value: V): [K, V][][] {
    const address = this.hash(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    const bucket = this.data[address];
    const element = bucket.find((element) => element[0] === key);
    if (!element) {
      bucket.push([key, value]);
      this._length++;
    } else {
      element[1] = value;
    }
    return this.data;
  }

  get(key: K): V | undefined {
    const address = this.hash(key);
    if (!this.data[address]) return undefined;
    const bucket = this.data[address];
    const element = bucket.find((element) => element[0] === key);
    return (element) ? element[1] : undefined;
  }

  getAll(): [K, V][] {
    const elements: [K, V][] = [];
    this.data.forEach((bucket) => {
      if (bucket) {
        bucket.forEach((element) => {
          elements.push(element);
        });
      }
    });
    return elements;
  }

  getAllKeys(): K[] {
    const keys: K[] = [];
    this.data.forEach((bucket) => {
      if (bucket) {
        bucket.forEach((element) => {
          keys.push(element[0]);
        });
      }
    });
    return keys;
  }

  delete(key: K): V | undefined {
    const address = this.hash(key);
    if (!this.data[address]) return undefined;
    const bucket = this.data[address];
    const element = bucket.find((element) => element[0] === key);
    if (!element) return undefined;
    bucket.splice(bucket.indexOf(element), 1);
    this._length--;
    return element[1];
  }

  get length(): number {
    return this._length;
  }

  [util.inspect.custom]() {
    return this.data;
  }
}

Si os interesa ver más cosas sobre programación esta es mi web donde subo algunos tutoriales https://blog.jcoder.es

Para el Delete, hice lo siguiente, quedo atento a sus aporte 😃

delete(key){
        const address=this.hashMethod(key);
        const currentBucket=this.data[address];
        if(currentBucket){
            for(let i=0;i<currentBucket.length;i++){
            if(currentBucket[i][0]===key){
                    return `Registro [${currentBucket.splice(i,1)}] Eliminado Exitosamente`               
                }
            }
        }
        return undefined
    }

En typescript :

De esta manera resolví HasTable.delete() y HasTable.getAllKeys()
¿Qué opinan?

delete (key) {
    const address = this.hashMethod(key)
    const bucket = this.data[address]
    if (bucket) {
      for (let i = 0; i < bucket.length; i++) {
        if (bucket[i][0] === key) return delete bucket.splice(i, 1)
      }
    }
    return undefined
  }

  getAllKeys () {
    let keys = this.data.flatMap(bucket => {
      if (!bucket) return []
      return bucket.map(record => record[0])
    })

    return keys
  }

Metodo getKeys:

 getKeys() {
        const keys = [];
        for (let i = 0; i < this.data.length; i++) {
            if (this.data[i]) {
                for (let j = 0; j < this.data[i].length; j++) {
                    keys.push(this.data[i][j][0]);
                }
            }
        }
        return keys;
    }

methdo getValues:

 getValues() {
        const values = [];
        for (let i = 0; i < this.data.length; i++) {
            if (this.data[i]) {
                for (let j = 0; j < this.data[i].length; j++) {
                    values.push(this.data[i][j][1]);
                }
            }
        }
        return values;
    }

metodo delete:

 delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    currentBucket.splice(i, 1);
                }
            }
        }
        return this.data;
    }

De hecho, otra forma de decirlo es que tenemos un array de tuplas

[ [ key, value ], [ key, value ] ]

Esta fue la forma en que lo hice

delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key) {
                    delete this.data[address];
                    return this.data;
                }
            }
        }
        return undefined;
    }

    getAllKeys() {
        return this.data.filter(set => set.length > 0).map(bucket => bucket[0][0]);
    }

Yo lo entendí así y así lo hice creo que esta bien

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }
  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1];
        }
      }
    }
    return undefined;
  }
  delete(key) {
    const address = this.hashMethod(key);
    if (this.data[address]) {
      const deleteValue = this.data[address][0]
      this.data.splice(address, 1)
      return deleteValue
    }
    return undefined
  }
  getAllKeys() {
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i]) {
        console.log(`Key: ${i} - value: ${this.data[i][0]}`);
      }
    }
  }
}

Les comparto mi solución al método remove(key)…

	remove(key) {
		const address = this.hashMethod(key);
		const currentBucket = this.data[address];
		let currentElement = undefined;
		let index = 0;
		let found = false;
		if (currentBucket) {
			for (let i = 0; i < currentBucket.length; i++) {
				if (found == false && currentBucket[i][0] === key) {
					currentElement = currentBucket[i];
					index = i;
					found = true;
				}
			}
		}
		if(found) {
			this.data[address].splice(index, 1);
			return currentElement;
		}
		return undefined;
	}

<code> 
```    public getAllBucketKeys(key : string) : string[]{
        let bucket : Hash<ValueType>[] = this.get(key)
        let keys : string[] = []
        bucket.map((member : Hash<ValueType>) : void => {
            keys.push(member.key)
        })
        return keys
    }

solución al reto de Remove y getAllKeys

 delete(key)
    {
        let keyFound = this.hashMethod(key);
       
        if(this.data[keyFound])
        {
            const lengthValueHash = this.data[keyFound].length;
            let  valueDelete;
            for(let i =0; i< lengthValueHash; i++)
            {
                if(this.data[keyFound][i][0] === key)
                {
                    valueDelete = this.data[keyFound][i];
                    if(this.data[keyFound].length>1)
                    {
                        delete this.data[keyFound][1];
                    }
                    if(this.data[keyFound].length === 1)
                    {
                        delete this.data[keyFound];
                    }

                }
            }
            return valueDelete;
        }
        return undefined;
       
    }

    getKeys()
    {
        let keys = [];
        for (let i = 0 ; i<this.data.length;i++)
        {
            
            if(this.data[i])
            {
             const element = this.data[i];
             
             for(let index = 0;index< element.length;index++)
             {
                
                keys.push(element[index][0]);
             }
             
              
            }
        }
        return keys;
    }

esta es la manera que hice el get , si no da un index que no existe entonces devuelve null sino pregunta si la longitud es mayor a 1, significa que hay colisión entonces busca los keys y guarda el key si lo encuentra sino directamente devuelve en la posición 1 ;

get(key){
        let keyFound = this.hashMethod(key);
        let indexValue = 0;
       
        if(this.data[keyFound])
        {
            const lengthValueHash = this.data[keyFound].length;
            if(lengthValueHash > 1)
            {
                for(let i =0; i< lengthValueHash; i++)
                {
                  if(this.data[keyFound][i][0] === key)
                  {
                    indexValue = i;
                  }
                }
            }
            return this.data[keyFound][indexValue][1];
        }
        return null;
       
       
    }

class HashTable {
constructor(size){
this.data =new Array(size);
}

hashMethod(key) {
    let hash = 0;
    for(let i = 0; i < key.length; i++){
        hash = (hash +key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
}

set(key,value){
    const address =this.hashMethod(key);
    if(!this.data[address]){
        this.data[address] =[];
    }
    this.data[address].push([key, value]);
    return this.data;
}

get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket){
        for(let i = 0; i < currentBucket.length; i++){
            if(currentBucket[i][0] === key){
                return currentBucket[i][1];
            }
        }
    }
    return undefined;

}

delete(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket){
        const value = currentBucket[0];
        currentBucket.splice(currentBucket,1);
        return value;

    }
    return undefined;
    
}

listarKeys(){
     var value = [];
     
    for(let i = 0; i < this.data.length; i++){
        if(this.data[i]){
            value.push(this.data[i][0][0])
        }
       
    }
    return value;

}

}

const myHashTable = new HashTable(50);

Elimina un item especifico segun su key

deleteItem(key){
    const address = this.hashMethod(key);
    if(this.data[address]){
      delete this.data[address];
    }else console.log("Not found");
    return this.data;
  }

Devuelve las entradas con su informacion almacenadas en el bucket

getAllKey(){
      const addresses = this.data.length;
      for(let i = 0; i < addresses; i++){
        if(this.data[i] != null){
          console.log(this.data[i][0]);
        }
      }
  }

Esta es mi implementación de getAllKeys y remove,

class hashTable {
    constructor(size){
        this.data = new Array(size);
    }

    hashMethod(key){
        let hash = 0;
        for (let i = 0; i < key.length; i++){
            hash = (hash + key.charCodeAt(i)*i) %this.data.length;
        }
        return hash;
    }

    set(key,value){
        const address = this.hashMethod(key);
        if(!this.data[address]){
            this.data[address] = [];
        }
        this.data[address].push([key,value]);
        return this.data
    }

    get(key){
        const address = this.hashMethod(key);
        const arrayIn = this.data[address];
        if(arrayIn != null){
            for (let i = 0; i<arrayIn.length; i++){
                if (key === arrayIn[i][0]){
                    return arrayIn[i];
                }
            }
        }

        return undefined;
    }


    getAllKeys(){
        const allKeys = []
        for (let i = 0;i<this.data.length;i++){
            const arrayIn = this.data[i];
            if (arrayIn){
                for (let j = 0;j<arrayIn.length;j++){
                    allKeys[allKeys.length] = arrayIn[j][0];
                }                
            }
        }
        return allKeys;
    }

    remove(key){
        const address = this.hashMethod(key);
        const arrayIn = this.data[address];
        if(arrayIn){
            if(arrayIn.length == 1){
                delete this.data[address]
            }
            else{   
                for (let i = 0; i<arrayIn.length; i++){
                    if (key === arrayIn[i][0]){
                        for (let j = 0; j<arrayIn.length-1-i;j++){
                            this.data[address][i] = this.data[address][i+1]; 
                        } 
                    }
                }
                this.data[address].pop();

            }
        }
        return undefined;
    }
}

const myNewArray = new hashTable(50); 

Yo llamo arrayIn a lo que en el video nombran como currentBucket porque ya lo había hecho y me dió flojera cambiarlo, saludos!

My code

	delete(key) {
		const address = this.hashMethod(key);
		delete this.data[address];
	}

	getAll() {
		const allKeys = [];
		for (const key in this.data) {
			if (Object.hasOwnProperty.call(this.data, key)) {
				allKeys.push(this.data[key]); 
			}
		}
		return allKeys.flat();
	}

Dejo la solución del reto

delete(key)
  {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]
    if(currentBucket)
    {
      if(currentBucket.length > 1)
      {
        for(let i=0; i< currentBucket.length; i++)
        {
          if(currentBucket[i][0] === key)
          {
            this.data[address].splice(i,1)
            return key
          }
        }
      }
      this.data[address].shift()
      return key
    }
    return undefined
  }


getKeys()
  {
    const keys = []
    for(let i=0; i<this.data.length; i++)
    {
      if(this.data[i])
      {
        if(this.data[i].length>1)
        {
          for(let j=0; j<this.data[i].length;j++)
          {
            keys.push(this.data[i][j][0])
          }
        }
        else keys.push(this.data[i][0][0])
      }
    }
    return keys
  }

Asi lo hice yo

delete(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    let deleted;
    if(currentBucket){
        if(currentBucket.length > 1){
            for(let i = 0; i< currentBucket.length; i++){
                if(currentBucket[i][0] === key){
                    deleted = currentBucket[i];
                    for(let idx = i; idx < currentBucket.length; idx++){
                        currentBucket[idx] = currentBucket[idx + 1];
                    }
                    currentBucket.pop();
                    return deleted;
                }
            }
        }
        deleted = currentBucket[0];
        delete currentBucket[0];
        return deleted;
    }
    return undefined;
}
clear(){
    this.data = new Array(this.size);
    return this.data;
}
¿Para que se usan? Las tablas de has son estructuras de datos asociativos y se usan principalmente para almacenar grandes volúmenes de información de manera que puedan ser accedidos de una forma más rápida. Dependiendo del algoritmo de hash utilizado son más o menos efectivos.

Comparto el Get para todos las key, vi soluciones complicadas, capaz la mia no es muy practica pero es más sencilla a las que vi:

getKeys(){
        var keys=[]
        for ( let i=0 ; i<=this.data.length ; i++ ) {
            if ( this.data[i] != undefined ) {
            keys.push( this.data[i] );
            }
        }
        return keys;
    }

Aqui esta mi codigo con el metodo delete. El unico detalle que encontre en esta clase es que pasa cuando quieres sobre escribir un valor, habria que crear un metodo update pues con el set no se puede a menos que se modidifique pero veo que serian demasiados pasos.
Tu que piensas?

class HashTable {
	constructor(size) {
		this.data = new Array(size);
	}
	hashFunctioner(key) {
		let hash = 0;
		for (let i = 0; i < key.length; i++) {
			hash = (hash + key.charCodeAt(i) * i) % this.data.length;
		}
		return hash;
	}
	setter(key, value) {
		const address = this.hashFunctioner(key);
		console.log(address);
		if (!this.data[address]) {
			this.data[address] = new Array();
		}
		this.data[address].push([key, value]);
		return this.data;
	}
	getter(key) {
		const address = this.hashFunctioner(key);
		const bucket = this.data[address];
		if (bucket) {
			for (let i = 0; i < bucket.length; i++) {
				if (bucket[i][0] === key) {
					return bucket[i][1];
				}
			}
		}
		return null;
	}
	deleter(key) {
		const address = this.hashFunctioner(key);
		const bucket = this.data[address];
		if (bucket) {
			for (let i = 0; i < bucket.length; i++) {
				if (bucket[i][0] === key) {
					bucket.splice(i, 1);
					return bucket;
				}
			}
		}
		return null;
	}
}
  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          this.data[address].splice(i, 1);
          return true;
        }
      }
    }
    return false;
  }
  getKeys() {
    const keys = [];
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i]) {
        for (let j = 0; j < this.data[i].length; j++) {
          keys.push(this.data[i][j][0]);
        }
      }
    }
    return keys;
  }

Holaaa, les dejo mi resolucion del reto.

//Meotdos para encontrar, eliminar,etc todos los datos

class HashTable {
    constructor(size){
        this.data = new Array(size);
    }
    //Las hashFucntion no las tenes que hacer, la realiad es que ya existen en github o google, una de ellas es la que tengo aca abajo,peero, lo mejor es googlear la mejor que se adapte a mi estilo.
    hashMethod(key) {
        let hash = 0;
        for(let i = 0; i < key.length; i++) {
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        return hash;
    }
    set(key,value){
        const address = this.hashMethod(key);
        if(!this.data[address]) {
            this.data[address] = [];
        } 
        this.data[address].push([key,value]);
        return this.data;
    }
    get(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address]
        if(currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key){
                    return currentBucket[i][1]
                }
            }
        }
    }
    delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address]
        if(currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key){
                  console.log(currentBucket)
                  
                 const inndex = currentBucket.indexOf(currentBucket[i])
                  console.log(inndex)
                  const deleted = currentBucket.splice(inndex,1)
                  console.log(currentBucket) 
                    
                }
            }
        }
    }
		getKeys(){
     const keys = []
     const concat = this.data.flat(1)
     console.log(concat)
     for(let i = 0; i < concat.length;i++) {
    		keys.push(concat[i][0])
  
     }
     console.log(keys)
   }

}



//address es el numero que genera la funcion hash con la key.
//key es la palabra que guardaremos
//value es un valor de lo que nos guste guaradar

const myHashTable = new HashTable(50);
myHashTable.set('Diego',2001)
myHashTable.set('Mariana',1342)
myHashTable.get('Mariana')
myHashTable.delete('Mariana')

Impresionante clase, me encanta

No lo se Rick, obtener el valor de un HashTable tiene una complejidad de O(1) y aquí parece O(n)

Aqui el codigo un poco mas pequeño utilizando la webAPI de find

get(key){
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]

    if(currentBucket){
        const value = currentBucket.find(item => item[0] === key)
        return value[1]
    }
    return undefined;
}

Metodos Borrrar y llavesObjetos!

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }
  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1];
        }
      }
    }
    return undefined;
  }

  borrar(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket){
      for(let i = 0 ; i < currentBucket.length; i++){
        if(currentBucket[i][0] === key){
          delete this.data[address];
          return currentBucket
        }
      }
    }
    return undefined
  }
  llavesObjeto() {
    const keys = [];
    for(let i = 0; i < this.data.length ; i++){
      if(this.data[i]){
        for(let e = 0; e < this.data[i].length ; e++){
          keys.push(this.data[i][e][0])
        }
      }
    }
    return keys;
  }
}

Mi código:
Me hubiera gustado no haber usado el método “splice”, pero no supe cómo hacer el “delete” y que el tamaño del array de keys con el mismo hash se redujera. COMENTARIOS POR FAVOR!

delete(key) {
  const address = this.hashMethod(key)
  const currentBucket = this.data[address]
  if (currentBucket) {
    for (let i = 0; i < currentBucket.length; i++) {
      if (currentBucket[i][0] === key) {
        currentBucket.splice(i, 1)
        return key
      }
    }
  }
  return false
}

getKeys() {
  return this.data.reduce((keysArray, values) => {
    const keys = values.map(([key]) => key);
    return keysArray.concat(keys)
  }, []);
}

Creo que el método “delete” no debería devolver el “value” por el principio de responsabilidad única. Estamos programando un delete, no un get(key).

Delete method:

  remove(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];

    if (currentBucket) {
      if (currentBucket.length > 1) {
        for (let i = 0; currentBucket.length; i++) {
          if (currentBucket[i][0] === key) {
            const value = currentBucket[i];
            currentBucket.splice(i, 1);
            return value;
          }
        }
      }
      if (currentBucket.length === 1) {
        const index = this.data.indexOf(currentBucket);
        this.data.splice(index, 1);
      }
    }
  }

Este man es muy inteligente 🤯

Aquí mi solución para los desafíos (son los métodos al fondo de la class, “delete()” y “getKeys()”):

class HashTable{
    constructor(size){
        this.data = new Array(size)
    }
    hashMethod(key){
        let hash = 0
        for(let i = 0; i < key.length; i++){
            hash = (hash + key.charCodeAt(i) * i) % this.data.length
        }
        return hash
    }

    set(key, value){
        const address = this.hashMethod(key)
        if(!this.data[address]){
            this.data[address] = []
        }
        this.data[address].push([key, value])
        return this.data
    }

    get(key){
        const address = this.hashMethod(key)
        const currentBuket = this.data[address]
        if(currentBuket){
            for(let i = 0; i < currentBuket.length; i++){
                if(currentBuket[i][0] === key){
                    return currentBuket[i][1]
                }
            }
        }
        return undefined
    }
    delete(key){
        const address = this.hashMethod(key)
        const currentBuket = this.data[address]
        let valueKey
        if(currentBuket){
            for(let i = 0; i < currentBuket.length; i++){
                if(currentBuket[i][0] === key){
                    valueKey = currentBuket[i]
                    currentBuket.splice(i, 1)
                }
            }
        }
        console.log(currentBuket.length, currentBuket)
        return valueKey
    }

    getKeys(){
        const allKeys = []
        for(let i = 0; i < this.data.length; i++){
            const keyType = this.data[i]
            console.log(keyType)
            if(Array.isArray(keyType) && this.data[i].length > 0){
                for(let indx = 0; indx < keyType.length; indx++){
                    allKeys.push(keyType[indx][0])
                }
            }
        }
        return allKeys
    }
}

Listo el reto de la clase, me gusto, me hizo pensar en las estructuras y usar otras cosas que no fueran los clásicos métodos que ofrece JavaScript

class hashTable {
  constructor() {
    this.data = Array(50);
  }
  hashMethod(key) {
    let hash = 0; 
    for (let i = 0; i < key.length; i++) {
      hash = ( hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = []
    }
    this.data[address].push([key, value]);
    return this.data;
  }
  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1];
        } 
      }
    }
    return undefined;
  }
  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          const item = `[${currentBucket[i][0]}: ${currentBucket[i][1]}] Deleted`
          delete currentBucket[i][0];
          delete currentBucket[i][1];
          return item;
        } 
      }
    }
    return "Not exist";
  }
  getAll() {
    const finded = []
    for (let i = 0; i < 50; i++) {
      const currentBucket = this.data[i]
      if(currentBucket) {
        for (let i = 0; i < currentBucket.length; i++) {
          if (currentBucket[i][0]){
            finded.push([currentBucket[i][0], currentBucket[i][1]])
          }
        }
      }
      
    }
    return finded
  }
}

const myHashTable = new hashTable();

myHashTable.set("Juan", 1990);
myHashTable.set("Elizabeth", 1996);
myHashTable.set("Diego", 1994);
myHashTable.set("Jose", 2000);
myHashTable.set("Juan", 1985);
myHashTable.set("Mariana", 1998);

myHashTable.get("Diego");

myHashTable.delete("Diego");

myHashTable.getAll();

Hola 😀.
Les comparto mi solución de los dos retos que nos han dejado. Gracias por su atención !

// Delete an element 

  deleteElement( key )
  {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]

    if(currentBucket)
    {
      for ( let i = 0 ; i < currentBucket.length ; i++ )
      {
        if( currentBucket[i][0] === key )
        {
          delete currentBucket[i]
        }
      } 
    }
    return undefined
  }

  // Return all the keys
  getAllKeys()
  {
    let listOfKeys = [  ]
    for ( let i =  0 ; i < this.data.length - 1 ; i++ )
    {
      if( this.data[i] !==  undefined )
      {
        for( let l = 0 ; l < this.data[i].length ; l++ )
        {
          listOfKeys.push( this.data[i][l][0] )
        }
      }
    }
    return listOfKeys
  }

Esta es una propuesta de la clase HashTable, junto con los métodos getAllKeys y delete 👇

class HashTable {

    constructor(size) {
        this.data = new Array(size);
    }

    hashMethod(key) {
        let hash = 0;
        for (let i = 0; i < key.length; i++) {
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        return hash;
    }

    set (key, value) {
        const address = this.#getAddress(key);
        if (!this.data[address]) {
            this.data[address] = [];
        }
        this.data[address].push([key, value]);
    }

    get (key) {
        const currentBucket = this.#getCurrentBucket(key);
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] == key) {
                    return currentBucket[i][1];
                }
            }
        }
        return undefined;
    }

    delete (key) {
        const currentBucket = this.#getCurrentBucket(key);
        if (currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    const item = currentBucket[i];
                    //delete currentBucket[i];
                    currentBucket.splice(i,1);
                    return item;
                }
            }
        }
        return undefined;
    }

    getAllKeys() {
        const keys = [];
        let key;
        let bucket;
        for(let i = 0; i < this.data.length; i++) {
            bucket = this.data[i];
            if (bucket) {
                for(let j = 0; j < bucket.length; j++) {
                    key = bucket[j];
                    if (key) {
                        console.log(key);
                        keys.push(key[0])
                    }
                }
            }
        }
        return keys;
    }

    #getAddress (key) {
        return this.hashMethod(key);
    }

    #getCurrentBucket (key) {
        const address = this.#getAddress(key);
        const currentBucket = this.data[address];
        return currentBucket;
    }
}

const myHashTable = new HashTable(50);

// TEST
myHashTable.set("Sandro", 1967);

console.log(myHashTable.data);

myHashTable.set("Mariana", 1997);
myHashTable.set("Diego", 2000);

console.log(myHashTable.data);

console.log(myHashTable.get("Sandro"));
console.log(myHashTable.get("Mariana"));
console.log(myHashTable.get("Diego"));
console.log(myHashTable.get("Julian"));

console.log(myHashTable.delete("Diego"));
console.log(myHashTable.data);

console.log(myHashTable.getAllKeys());
/*Es el mismo aporte de la clase pasada, con el plus que nuestro intento de comprobacion dedujo el metodo get de esta clase*/
class HashTable {
    constructor(size) {
        this.data = new Array(size)
    }
    hashMethod(key) {
        let hash = 0;
        for (let i = 0; i < key.length; i++) {
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        return hash
    }
    set(key, value) {
        const address = this.hashMethod(key)
        if (!this.data[address]) {
            this.data[address] = []
        }
        this.data[address].push([key, value])
        return this.data
    }
    //IMPLEMENTACION DEL GET DEDUCIDO DE FORMA SIMPLE
    // get(key) {
    //     const address = this.hashMethod(key)
    //     return this.data[address]
    // }
    //LA FORMA EXACTA PARA IDENTIFICAR EL VALOR PRECISO
    get(key) {
        const address = this.hashMethod(key)
        const currentBucket = this.data[address]
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    return currentBucket[i][1]
                }
            }
        } else {
            return undefined
        }
    }
}

//Generamos 50 buckets
const myHashTable = new HashTable(50)
// console.log(myHashTable)
myHashTable.set("Diego", 1990)
myHashTable.set("Mariana", 1998)
myHashTable.set("Alejandra", 2000)
// const address = myHashTable.hashMethod("Diego")
// console.log(myHashTable.data[address])
// console.log(myHashTable.data[10])
/**La funcion get se dedujo al tratar de comprobar como mi comentario de la clase pasada */
console.log(myHashTable.get('Diego'))
// console.log(myHashTable)



getAllKeys(){
        return this.data.reduce((keys, bucket) => {
            const bucketKeys = bucket.map(key => key[0]);
            return keys.concat(bucketKeys);
        }, []);
    }

Los métodos

delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    currentBucket.splice(i, 1);
                    if (currentBucket.length === 0) {
                        delete this.data[currentBucket];
                    }
                    return this.data;
                }
            }
        }
        return undefined;
    }

    getAllKeys(){
        const keys = [];
        this.data.forEach(bucket =>{
            bucket.forEach(array => {
                keys.push(array[0])
            })
        })
        return keys;
    }

Les comparto el método para solamente obtener las keys, de nuestra hashTable, observen que en realidad tenemos un array, de arrays, de arrays, es decir 3 arrays anidados, a mi m me voló la cabeza porque apenas entendí eso, cuando tenemos un adress, tenemos tres arrays anidados, por que no estamos accediendo a ningún espacio específico, estamos desde el scope más general con el que podemos acceder a nuestra hashTable

  getKeys(){
        let keys = []
        console.log(this.data)
        for(let i=0; i<this.data.length; i++){
            if (this.data[i]){
                keys.push(this.data[i][0][0])
            }
        }

        return keys ? keys : undefined
    }

Comporto mi codigo de la clase y el reto

class HashTable {
    constructor(size){
        this.data = new Array(size);
    }
    hashMethod(key){
        let hash = 0;
        for (let i = 0; i < key.length; i++){
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        return hash;
    }
    set(key, value){
        const address = this.hashMethod(key);
        if(!this.data[address]){
            this.data[address] = [];
        }
        this.data[address].push([key, value]);
        return this.data;
    }
    keys() {
        const buckets = Object.values(this.data);
        let keys = [];
        buckets.forEach(bucket => {
            bucket.forEach(array => keys.push(array[0]));
        });
        return keys;
    }
    get(key){
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key) {
                    console.log(currentBucket);
                    return currentBucket[i][1];
                }
            }
        }
        return undefined;
    }
    delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket) {
            for(let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key) {
                    let arrayDelete = currentBucket[i];
                    currentBucket.splice(i, 1);
                    return arrayDelete;
                }
            }
        }
        return undefined;
    }
}

const myHashTable = new HashTable(50);

Les dejo mi método delete:

Reto 1 de la clase

deleted(key){
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket){   
            delete this.data[address];
            return this.data[address];
        }else{
            alert('no existe ese key');
        }
    }

Reto 2 de la clase

 getAllValues(){
        for (let i = 0; i < this.data.length; i++) {
            const bucket = this.data[i];
            if(bucket !== undefined){
                console.log(`key: ${bucket[0][0]} value: ${bucket[0][1]}` );
            }
        }
    }

reto satisfactorio, Ok!, en la imagen en apartado verde tengo una colision de hash table donde, con el metodo delete se borra el key/value del array’[0], entonces la informacion contenedora del bucket random, al momento de aplicar el metodo delete, me retorno un array vacio, como el bucket 49, la idea es que se borrara todo el array como lo que sucede en la collision cierto?.. ahi tengo dudas campeon. Pero bueno esto es un reto… aun hace falta.

 remove(key) {
    const address = this.hashMethode(key);
    if(this.data[address] && this.data[address].length) {
      for (let i = 0; i < this.data.length; i++) {
        if(this.data[address][i][0] === key) {
          this.data[address].splice(i, 1);

          return `${key} was erase`;
        }
      }
    } else {
      return `The key ${key} does not exist`;
    }
  }
  getAllKeys() {
    return this.data.reduce((acc, val) => {
      if(val) {
        acc.push(...val.map(element => element[0]));
        return acc;
      }
    }, [])
  }

Listos los retos 😄

unset(key){
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]
    if(currentBucket){
        for(let i = 0; i < currentBucket.length; i++){
            if(currentBucket[i][0] === key ){
                const eliminateValue = currentBucket[i]
                this.data[address].splice(i,1)
                return eliminateValue
            }
        }
    }
}   

allKeys(){
    const listOfKeys = []
    this.data.forEach(element => {
        element.forEach(element =>{
            listOfKeys.push(element[0])
        })
    })
    return listOfKeys
}


Mi solución al reto 😀:

delete(key) {
  const address = this.hashMethod(key);
  const currentBucket = this.data[address];
  if (currentBucket) {
    for (let i = 0; i < currentBucket.length; i++) {
      if (currentBucket[i][0] === key) {
        let deletedItem = currentBucket[i];
        currentBucket.splice(i, 1);
        return deletedItem;
      }
    }
  }
  return undefined;
}

getAllKeys() {
  let keys = [];
  for (let i = 0; i < this.data.length; i++) {
    if (!this.data[i]) continue;
    for (let j = 0; j < this.data[i].length; j++) {
      keys.push(this.data[i][j][0]);
    }
  }
  return keys;
}

Comparto mi solución del reto

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }

  hashMethod(key) {
    let hash = 0;
    for (let chart of key) {
      hash += chart.charCodeAt(0);
    }
    hash = hash % this.data.length;
    return hash;
  }

  insert(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    if (this.data[address].find((bucket) => bucket.key === key)) {
      return console.log("The key was assigned before");
    }
    this.data[address].push({ key, value });
    return this.data;
  }

  search(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    return currentBucket
      ? currentBucket.find((element) => element.key === key).value
      : undefined;
  }
  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      const index = currentBucket.findIndex((element) => element.key === key);
      if (index !== -1) {
        this.data[address].length === 1
          ? delete this.data[address]
          : this.data[address].splice(index, 1);
      }
      return this.data;
    }
  }
  keys() {
    return this.data.flat().map((element) => element.key);
  }
}

Mi aporte para el método “remove”:

remove(key){
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket){
            for(let i = 0; i < currentBucket.length; i++){
                if(currentBucket[i][0] === key){
                    delete currentBucket[i];
                    currentBucket[i] = currentBucket[i+1];
                    currentBucket.length--;
                }
            }
            if(currentBucket.length == 0){
                delete this.data[address];
            }
            return myHashTable.data;
        }
        return undefined;
    }

Ejercicio de remove y getAllKeys 👌👨‍💻

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }

  get(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket){
      for(let i = 0; i < currentBucket.length; i++){
        if(currentBucket[i][0] === key){
          return currentBucket[i][1];
        }
      }
    }
    return undefined;
  }
  
  remove(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket){
     for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          const deletedValue = this.data[address][i];
          this.data[address].splice(i, 1);
          return deletedValue;
        }
      }
  
    }
    return undefined;
  }
  
  getAllKeys(){
    return this.data.reduce((acu,current) =>{
      if(current) acu.push(...current.map(item=>item[0]));
      return acu;
    },[])
    
  }
}

Aquí mi metodo getKeys.

getKeys(){
    let keyArray = [];
    for (let i = 0; i < this.data.length; i++){
        let currentBucket = this.data[i];
        if (!currentBucket){
            continue;
        }
        for (let j = 0; j < currentBucket.length; j++){
            keyArray.push(currentBucket[j][0]);
        }
    }

    return keyArray;
}

Aquí mi metodo remove.

remove(key){
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    let item;
    if (currentBucket){
        for(let i = 0; i < currentBucket.length; i++){
            if (currentBucket[i][0] === key){
                item = currentBucket[i].splice(i);
                return item;
            }
        }
    }
}

mi propuesta:

    getAllKeys() {
        return this.data
            .map((bucket) => {
                return bucket.reduce((prev, curr) => {
                    prev.push(curr[0]);
                    return prev;
                }, []);
            })
            .flat();
    }
    remove(key) {
        const address = this.hashMethod(key);
        if (this.data[address]) {
            this.data[address] = this.data[address].filter(
                (item) => item[0] !== key
            );
            if (this.data[address].length === 0) delete this.data[address];
        }
        return this.data;
    }

Les comparto una forma más javascriptística de los métodos implementados en clase y la solución al desafío usandojsdocs:

class HashTable {
  /**
   * @param {Number} size
   */
  constructor(size) {
    /**
     * @type {[[[string, any]]]} An array of arrays whose elements are arrays where the first index is a string and the second one is the value.
     * @public
     */
    this.data = new Array(size)
  }

  /**
   * Method that hash an input string 
   * @param {String} key
   * @returns {Number}
   */
  hashMethod(key) {
    let hash = 0
    for (let i = 0; i < key.length; i++)
      hash = (hash + key.charCodeAt(i) * i) % this.data.length

    return hash
  }

  /**
   * @param {String} key
   * @param {Any} value
   * @returns {[[[string, any]]]}
   */
  set(key, value) {
    const address = this.hashMethod(key)

    if (!this.data[address])
      this.data[address] = []

    this.data[address].push([key, value])

    return this.data
  }

  /**
   * Returns the value stored in with the key
   * @param {String} key
   * @returns {Any|undefined} The value of the key if it was found, or undefined if it wasn't
   */
  get(key) {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]

    if (currentBucket)
      return currentBucket.find(b => b[0] === key)[1]

    return undefined
  }

  /**
   * @param {String} key 
   * @returns {[[[string, any]]]}
   * @throws an error if the key is not in the hashTable
   */
  delete(key) {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]

    if (currentBucket) {
      this.data[address] = currentBucket.filter(e => e[0] !== key)

      return this.data
    }

    throw new Error('The specified key doesn\'t exists')
  }

  /**
   * @returns {[string]} all the keys from the hashTable
   */
  getAllKeys() {
    /**
     * @type {[string]}
     */
    const acc = []

    return this.data.reduce((keys, bucket) => {
      if (bucket)
        keys.push(...bucket.map(e => e[0]))

      return keys
    }, acc)
  }
}

aporte de clase: Entender los metodos y sus funciones es vital para comprender las clases.

get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if(currentBucket[i][0] === key) {
          return currentBucket[i][1];
        };
      };
    };
    return undefined;
  };

Mi propuesta para el reto .getAllKeys() fue la siguiente.
En lugar de crear un nuevo método por completo, preferí modificar el método .get() que ya tenemos. Lo que hice fue agregarle un segundo parámetro, donde el usuario pusiera que era lo que quería obtener, ya sea clave (‘key’) o el valor (‘value’). Aunque si el usuario no pasa el segundo parámetro, el programa regresa por default el valor y no la clave.
Les comparto mi código.

      //This method allows receive the data from a bucket
    get(key,desireItem){
        const address=this.hashMethod(key); //This is the address where data stores
        //This if cycle verifies that the bucket exits
        if(this.data[address]){
            //This for loop go through the whole arragement in order to find the data that we are looking for
            for(let i=0;i<this.data[address].length;i++){
                //This if cycle just verifies if the bucket is equal to the key
                if(this.data[address][i][0]===key){
                    if(desireItem===undefined || desireItem==='value'){
                        return this.data[address][i][1];
                    } else if(desireItem==='key'){
                        return this.data[address][i][0];
                    } else{
                        return undefined;
                    }
                }
            }
        }else{
            return undefined;
        }
    }

Solución al reto, método remove y getAllKeys

Mi código por si les interesa:

class HashTable {
	constructor(size) {
		this.data = new Array(size);
	}

	hashMethod(key) {
		let hash = 0;

		for (let i = 0; i < key.length; i++) {
			hash = (hash + key.charCodeAt(i) * i) % this.data.length;
		}

		return hash;
	}

	set(key, value) {
	    const address = this.hashMethod(key);
	
	    if (!this.data[address]) {
	      this.data[address] = [];
	    }
	
	    this.data[address].push([key, value]);
	
	    return this.data;
	}

	get(key) {
		const address = this.hashMethod(key);
		const currentBucket = this.data[address];

		if (currentBucket) {
			for(let bucket of currentBucket) {
				if (bucket[0] === key) {
					return bucket[1];
				}
			}
		}
		return undefined;
	}

	delete(key) {
		const address = this.hashMethod(key);
		const currentBucket = this.data[address];

		if (currentBucket) {
			if (currentBucket.length === 1) {
				delete this.data[address];
			} else if (currentBucket.length > 1) {
				for(let i = 0; i < currentBucket.length; i++) {
					if (currentBucket[i][0] === key) {
						delete currentBucket[i];
						break;
					}
				}
			}
		}
	}

	getKeys() {
		let keys = [];

		for (let i = 0; i < this.data.length; i++) {
     		if(this.data[i]) {
        		const bucket = this.data[i].map(m => m[0]);
        		keys = [...keys, ...bucket];
      		}
		}

    	return keys;
  	}
}

const myHashTable = new HashTable(50);

Solución del reto para borrar un elemento de la tabla

delete(key)
    {
        const address = this.hashMetod(key);
        const currentBucket = this.data[address];
        if(currentBucket)
        {
            for(let i = 0; i < currentBucket.length; i++)
            {
                if(currentBucket[i][0] === key)
                {
                    delete currentBucket[i];
                    return this.data[address];
                }
            }
        }
        return undefined;
    }

Al momento de borrar el elemento me di cuenta de que el array queda del mismo tamaño y si vuelve a haber una colision se crea otra posicion, no se como arreglar eso Help me please

class HashTable {
	constructor(size) {
		this.data = new Array(size);
	}
	hashMethod(key) {
		let hash = 0;
		for (let i = 0; i < key.length; i++) {
			hash = (hash + key.charCodeAt(i) * i) % this.data.length;
		}
		return hash;
	}
	set(key, value) {
		const address = this.hashMethod(key);
		if (!this.data[address]) {
			this.data[address] = [];
		}
		this.data[address].push([key, value]);
		return this.data;
	}
	get(key) {
		const address = this.hashMethod(key);
		const currentBucket = this.data[address];
		if (currentBucket) {
			for (let iterator = 0; iterator < currentBucket.length; iterator++) {
				if (currentBucket[iterator][0] === key) {
					return currentBucket[iterator][1];
				}
			}
		}
		return undefined;
	}
	getKeys() {
		const arr = this.data.filter((e) => e);
		const arrFlatten = arr.reduce((acc, cur) => acc.concat(cur), []);
		for (let key = 0; key < arrFlatten.length; key++) {
			console.log(arrFlatten[key][0]);
		}
	}
	getValues() {
		const arr = this.data.filter((e) => e);
		const arrFlatten = arr.reduce((acc, cur) => acc.concat(cur), []);
		for (let key = 0; key < arrFlatten.length; key++) {
			console.log(arrFlatten[key][1]);
		}
	}
	delete(key) {
		const address = this.hashMethod(key);
		delete this.data[address];
	}
}

const myHashTable = new HashTable(50);
console.log(myHashTable);
myHashTable.set('Diego', 1990);
myHashTable.set('Mariana', 1998);
myHashTable.set('Alejandra', 2000);
myHashTable.delete('Alejandra');
console.log(myHashTable);
myHashTable.getKeys();
myHashTable.getValues();

mostrar todas

getKeys() {
        const buckets = this.data.length;
        for (let i = 0; i < buckets ; i++) {
            if(this.data[i]){
                console.log(this.data[i]) 

            }
        }
    }

Que tal amigos.
Estos son los methods que yo hice, espero su feedback.

  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          delete currentBucket[i];
          return currentBucket;
        }
      }
    }
    return undefined;
  }

  getNames() {
    const buckets = this.data.length;
    for (let i = 0; i < buckets ; i++) {
      console.log(this.data[i]) 
    }
  }

Aqui está todo mi código

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }
  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }
  get(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1];
        }
      }
    }
    return undefined;
  }

  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          delete currentBucket[i];
          return currentBucket;
        }
      }
    }
    return undefined;
  }

  getNames() {
    const buckets = this.data.length;
    for (let i = 0; i < buckets ; i++) {
      console.log(this.data[i]) 
    }
  }
}

const myHashTable = new HashTable(50);

myHashTable.set("Ivan", 1996);
myHashTable.set("Juan", 1989);
myHashTable.set("Eduardo", 1999);
myHashTable.set("Martin", 2004);

ASPTM, De Granda hace que un tema, en mi opinión, super mega recontra complicado sea entendible a la perfección :’)

Establecí un método (erase) para eliminar el item no importa si escribes el “key” o el “value”, reconocerá ambos. También hice el getKey que solicita el “value” y regresa el “key”.

class HashTable {
    constructor(size) {
        this.data = new Array(size);
    }

    hashMethod(key) {
        let hash = 0;
        for (let i = 0; i < key.length; i++) {
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        console.log(hash);
        return hash;
    }
    
    set(key, value) {
        const address = this.hashMethod(key);
        if(!this.data[address]) {
            this.data[address] = [];
        }
        this.data[address].push([key, value]);
        return this.data;
    }

    getValue(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket) {
            for(let i=0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key) {
                    return currentBucket[i][1];
                }
            }
        }
        return undefined;
    }

    getKey(value) {
        for(let i = 0; i < this.data.length; i++) {
            if(this.data[i]) {
                const innerBucket = this.data[i][0];
                if(innerBucket[1] === value) {
                    return innerBucket;
                }
            }
        }
    }

    erase(data) {
        for(let i=0; i<this.data.length; i++) {
            if(this.data[i]) {
                if(this.data[i][0][1] === data) {
                    delete this.data[i];
                }
                if(this.data[i][0][0]=== data) {
                    delete this.data[i];
                }
            }
        }
    }
}

const hash_table = new HashTable(50);

hash_table.set("Devora", 1998);
hash_table.set("Alejandro", 1994);
hash_table.set("Leonidas", 1991);

console.log(hash_table);

Así mis metodos

  getKeys(){
    const keys = [];
    for(let j = 0; j< this.data.length -1; j++){
      const currentBucket = this.data[j];
      if(currentBucket){
        for(let i= 0;i < currentBucket.length; i++){
          keys.push(currentBucket[i][0]);
        }
      }
    }
    return keys;  
  }

  remove(key){
    const adress = this.hashMethod(key);
    const currentBucket = this.data[adress];
    if(currentBucket){
      for(let i= 0;i < currentBucket.length; i++){
        if(currentBucket[i][0] === key){
          this.data[adress].splice(i,1);
          return currentBucket;
        }
      }
    }
    return undefined;
  }

Les comparto mis dos métodos
Estuvo mirando como borrar el key pero no logre, si alguien sabe me escribe por favor

delete (key) {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          delete currentBucket[i]
          console.log(`El elemento ${key} fue borrado satisfactoriamente`)
          return true
        }
      }
      return false
    }
    return console.log(`El elemento ${key} no se encuentra en la lista`)
  }

  list () {
    for (const i in this.data) {
      if (this.data[i] !== undefined) {
        console.log(`key ${i} : ${this.data[i]}`)
      }
    }
  }

esta es mi solución 😨 la comenté un poco

Mi implementación con los retos!

class HashTable {
    constructor(size) {
        this.data = new Array(size);
    }
    // hash function
    hashMethod(key){
        let hash = 0;
        for(let i=0; i<key.length; i++){
            hash = (hash + key.charCodeAt(i)*i) % this.data.length;
        }
        return hash;
    }
    //insertar un valor a la hash table
    set(key, value) {
        const address = this.hashMethod(key);
        if(!this.data[address]){
            this.data[address] = [];
        }
        this.data[address].push([key, value]);
        return this.data;
    }
    //obtener un valor de la hash table teniedo su key
    get(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket){
            for(let i=0;i<currentBucket.length;i++){
                if(currentBucket[i][0] === key){
                    return currentBucket[i][1];
                }
            }
        }
        return undefined;
    }
    //eliminar un elemento
    delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        let keyEliminated;
        if(currentBucket){
            for(let i=0;i<currentBucket.length;i++){
                if(currentBucket[i][0] === key){
                    keyEliminated = currentBucket[i];
                    currentBucket.splice(i,1);
                    return keyEliminated;
                }
            }
        }
        return undefined;
    }
    //obtener todos los key
    getKeys() {
        const keys = [];
        if(this.data.length>0){
            for(let i=0;i<this.data.length;i++){
                if(this.data[i]){
                    for(let j=0;j<this.data[i].length;j++){
                        keys.push(this.data[i][j][0]);
                    }
                }
            }
            return keys;
        }
        return undefined;
    }
}

const myHashTable = new HashTable(50);

A continuación dejo mi respuesta, la realicé en base a las clases que hemos visto.

 delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    const eliminado = currentBucket[i];
                    for (let j = i; j < currentBucket.length - 1; j++) {
                        currentBucket[j] = currentBucket[j + 1];
                    }
                    delete currentBucket[currentBucket.length - 1];
                    currentBucket.length--;
                    if (currentBucket == "") {
                        delete this.data[address];
                    }
                    return eliminado;
                }
            }
        }
        return undefined;
    }
    getAllKeys(){
        for (let i = 0; i < this.data.length; i++){
            if(this.data[i]){
                for(let j = 0; j < this.data[i].length;j++)
                    console.log(this.data[i][j][0]);
            }
       }
    }

Reto

set
El método no considera que pasa si existe un key repetido, en este caso se puede hacer que los otros metodos consideren estos elementos repetidos con un recorrido para mostrar sus valores o simplemente restringir al método set el no poder ingresar keys repetidos; es el que yo consideré. Les dejo el código

  set(key, value) {
    let exist = 0;
    const address = this.hashMethod(key);
    if(!this.data[address]) {
      this.data[address] = [];
    }
    for(let i = 0; i < this.data[address].length; i++) {
      if(this.data[address][i][0] === key) {
        exist = 1;
      }
    }
    if(!exist) {
      this.data[address].push([key, value]);
      return this.data;
    }
    return new Error("Existing value");
  }

getAllKeys

  getAllKeys() {
      const allKeys = [];
      for(let i = 0; i < this.data.length; i++) {
        if(this.data[i]) {
          for(let j = 0; j < this.data[i].length; j++) {
            allKeys.push(this.data[i][j][0]);
          }
        }
      }
      if(allKeys.length > 0) {
        return allKeys;
      }
      return undefined;
  }

delete

  delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if(currentBucket) {
      for(let i = 0; i < currentBucket.length; i++) {
        if(currentBucket[i][0] === key) {
          const deletedValue = currentBucket[i];
          currentBucket.splice(i, 1);
          return deletedValue;
        }
      }
    }
    return undefined;
  }
remove(key){
        const address=  this.hashMethod(key);
        const currentBucket= this.data[address];
        if(currentBucket){
            for (let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0]=== key){
                    const item= currentBucket[i];
                    currentBucket.splice(i,1)
                    return item;
                }   
            }
        }
        return 'Not founded'
    }
    getAllKeys(){
        let allKeys=[];
        for (let i = 0; i < this.data.length; i++) {
            if(this.data[i]){
                for (let j = 0; j < this.data[i].length; j++) {
                    allKeys.push(this.data[i][j][0]);
                }
            }
            
        }
        return allKeys;
    }```

Solucion al reto

// metodo para borrar elemento a traves de su key
delete(key){
    const address = this.hashMethod(key); // obtengo la direccion
    const currentBucket = this.data[address]; // obtengo el bucket

    if (currentBucket) {  // verifico que exista el bucket
        // recorro el bucket y busco la clave o key
        for (let i = 0; i < currentBucket.length; i++) {
            
            // si el currentBucket[i][0] es igual al key , se trata del elemento que quiero borrar
            if (currentBucket[i][0] === key) {
                delete currentBucket[i][0];
                delete currentBucket[i][1];
                return true;
            }
        }
        
    }

    // si no existe devuelvo false
    return false;
}



// obtengo todas las keys

getKeys(){
    let keys = [];
    let currentKey= '';
    //let keyIndex = 0; 

    // recorro todos los buckets
    for(let i = 0 ; i < this.data.length ; i++){
        
        if( typeof this.data[i] != 'undefined'  ){ // tiene algo en el bucket
            for(let j=0 ; j<this.data[i].length ; j++){
                currentKey = this.data[i][j][0];
                
                // mi solucion, funcionaba
                //keys[keyIndex] = currentKey; 
                //keyIndex++;

                // me gusta mas esta que encontre en platzi
                keys.push(currentKey);
                
            }
        }
        
        
    }
    return keys;
}

Delete Method

delete(key) {
    const address = this.hashMethod(key);
    const currentBucket = this.data[address];
    if (currentBucket) {
      for(let i = 0; i < currentBucket.length; i++) {
        if(currentBucket[i][0] === key) {
          delete currentBucket[i];
        }
      }
    }
    if (currentBucket.every(item => !item)) {
      delete this.data[address];
    }
    return undefined;
  }
delete(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        let removedElement;
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    removedElement = currentBucket[i];
                    delete this.data[address];
                    return removedElement;
                }
            }
        }
        return removedElement;
    }
    getKeys() {
        let keys = [];
        for (let i = 0; i < this.data.length; i++) {
            let currentBucket = this.data[i];
            if (currentBucket) {
                for (let j = 0; j < currentBucket.length; j++) {
                    if (currentBucket[j]) {
                        keys.push(currentBucket[j][0]);
                    }
                }
            }
        }
        return keys;
    }
keys() {
		const keys = []
		for (let i = 0; i < this.data.length; i++) {
			if (this.data[i]) {
				this.data[i].forEach((item) => keys.push(item[0]))
			}
		}
		return keys
	}

mis metodos de delete y get_keys

delete(key) {
    const address = this.hash_method(key)
    const currentBuquet = this.data[address]

    if (currentBuquet) {
      for (let i = 0; i < currentBuquet.length; i++) {    
        if (currentBuquet[i][0] === key) {
          const deletedItem = currentBuquet[i]
          this.data[address].splice(i, 1);
          return deletedItem
        }    
      }
    }

    return undefined
  }

  get_keys(){
    let allKeys = []

    for (let i = 0; i < this.data.length; i++) {
      const buquet = this.data[i]
      if (buquet) {
        for (let j = 0; j < buquet.length; j++) {
          allKeys.push(buquet[j][0])          
        }
      }
    }

    return allKeys
  }

Les dejo la solución de los retos finales empleando typescript

class HashTable {
    data: Array<Array<Array<number | string>>>;
    constructor(size: number) {
        this.data = new Array(size);
    }
    hashMethod(key: string) {
        let hash = 0;
        for (let i = 0; i < key.length; i++) {
            hash = (hash + key.charCodeAt(i) * i) % this.data.length;
        }
        return hash;
    }

    set(key: string, value: string | number) {
        const address: number = this.hashMethod(key);
        if (!this.data[address]) {
            this.data[address] = [];
        }
        this.data[address].push([key, value]);
        return this.data;
    }
    get(key: string) {
        const address: number = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    return currentBucket[i][1];
                }

            }
        }
        return undefined;
    }
    delete(key: string) {
        const address: number = this.hashMethod(key);
        const currentBucket = this.data[address];
        if (currentBucket) {
            if (currentBucket.length === 1) {
                delete this.data[address];
                return;
            }
            for (let i = 0; i < currentBucket.length; i++) {
                if (currentBucket[i][0] === key) {
                    const deletedElement = currentBucket[i][1];
                    delete currentBucket[i];
                    return deletedElement;
                }
            }
        }
    }
    getKeys() {
        const keys: Array<string | number> = [];
        this.data.forEach(element => {
            if (element) {
                element.forEach(array2 => {
                    keys.push(array2[0])
                });
            }
        });
        return keys;
    }
}

const myHashtable = new HashTable(50);
myHashtable.set('Diego', 1990);
myHashtable.set('Sandra', 1995);
myHashtable.set('Michael', 2005);
myHashtable.delete('Michael')
console.log(myHashtable.getKeys());

Mi código del reto con algunos cambios para validar escenarios donde el address no ha sido asignado.

class HashTable {
  constructor(size){
    this.data = new Array(size)
  }

  hashMetod(key){
    let hash = 0;
    for (let i = 0; i < key.length ; i++){
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }

  set(key, value){
    const addres = this.hashMetod(key);
    if(!this.data[addres]){
      this.data[addres] = []
    }

    this.data[addres].push([key,value]);
    return this.data;

  }

  get(key){
    const address = this.hashMetod(key)
    // Validar address
    if(!this.data[address]){
      return undefined
    }
    const currentBucket = this.data[address]
    for (let i = 0; i < currentBucket.length; i++) {
      if(currentBucket[i][0] === key){
        return currentBucket[i][1]
      }
    }
    return undefined
  }

  delete(key){
    const address = this.hashMetod(key)
    if(!this.data[address]){
      return undefined
    }

    const currentBucket = this.data[address]
    let bucketIndex = null
    let bucketValue = null 

    for (let i = 0; i < currentBucket.length; i++) {
      if(currentBucket[i][0] === key){
        bucketValue = currentBucket[i]
        bucketIndex = i
        break
      }
    }

    //Validamos que el valor haya existido en el bucket
    if(bucketIndex === null){
      return undefined
    }
    
    this.data[address].splice(bucketIndex, 1)

    if(this.data[address].length === 0){
      delete this.data[address]
    }

    return bucketValue
  }

  getKeys(){
    let keys = []

    this.data.forEach(bucket =>{
      bucket.forEach(element =>{
        keys.push(element[0])
      })
    })

    return keys
  }

}


Revisen mi codigo y me comentan, por que creo que se puede optimizar bastante:

    delete(key){
        const address = this.hashFunction(key);
        const currentBucket = this.data[address];

        if(currentBucket){
            for(let i = 0; i < currentBucket.length; i++){
                if(currentBucket[i][0] === key){
                    delete currentBucket[i]
                }
            }
        }
        return this.data;
    }
    getKeys(){
        let allKeys = []
        for(let i = 0; i < this.data.length ; i++){
            if( this.data[i]){
                 allKeys.push(this.data[i])
            }
        }
        return allKeys
    }

Solucion al reto de delete y get Keys 👨‍💻

class HashTable {
  constructor(size) {
    this.data = new Array(size)
  }

  hashMethod(key) {
    let hash = 0
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length
    }

    return hash
  }
  get(key) {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]
    if (currentBucket) {
      for (let i = 0; i < currentBucket.length; i++) {
        if (currentBucket[i][0] === key) {
          return currentBucket[i][1]
        }
      }
    }
  }
  set(key, value) {
    const address = this.hashMethod(key)
    if (!this.data[address]) {
      this.data[address] = []
    }

    this.data[address].push([key, value])
  }

  delete(key) {
    const address = this.hashMethod(key)
    const currentBucket = this.data[address]

    for (let i = 0; i < currentBucket.length; i++) {
      if (currentBucket[i][0] === key) {
        delete currentBucket[i]
      }
    }
  }

  getKeys() {
    const keys = []
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i]) {
        const currentBucket = this.data[i]
        for (let i = 0; i < currentBucket.length; i++) {
          keys.push(currentBucket[i][0])
        }
      }
    }
    console.log(keys)
    return keys
  }
}

const myTable = new HashTable(50)
myTable.set('Diego', 2003)
myTable.set('Mariana', 2005)
myTable.set('Adrian', 2009)
console.log(myTable.get('Diego'))
myTable.getKeys()

Mi solución a remove

remove(key) {
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket){
            for (let i = 0; i < currentBucket.length; i++) {
                if(currentBucket[i][0] === key){
                    const item = currentBucket[i];
                    currentBucket.splice(i, 1);
                    return item;
                }
            }
        }
        return `No existe`;
    }
getAllKeys() {
        const keys = [];
        for (let i = 0; i < this.data.length; i++) {
            if(this.data[i]){
                for (let j = 0; j < this.data[i].length; j++) {
                    keys.push(this.data[i][j][0]);
                }
            }
        }
        return keys;
    }

Comparto mi solución a los problemas. Adicione un metodo _find para reducir el codigo repetido entre la función delete y get.

class HashTable {
  constructor(size) {
    this.data = new Array(size);
  }
  hashMethod(key) {
    let hash = 0;
    for (let i = 0; i < key.length; i++) {
      hash = (hash + key.charCodeAt(i) * i) % this.data.length;
    }
    return hash;
  }

  set(key, value) {
    const address = this.hashMethod(key);
    if (!this.data[address]) {
      // prevent undefined errors
      this.data[address] = [];
    }
    this.data[address].push([key, value]);
    return this.data;
  }

  _find(key, onSuccess) {
    const hash = this.hashMethod(key);
    const bucket = this.data[hash];
    if (!bucket) {
      return undefined;
    }
    for (let index = 0; index < bucket.length; index++) {
      if (bucket[index][0] === key) {
        return onSuccess(bucket[index], index);
      }
    }
    return undefined;
  }

  get(key) {
    return this._find(key, (list) => {
      console.log(list);
      return list[1] || undefined;
    });
  }
  delete(key) {
    return this._find(key, (_, index) => {
      const hash = this.hashMethod(key);
      this.data[hash].splice(index, 1);
      return this.data;
    });
  }
  getAllKeys() {
    const keys = [];
    for (let index = 0; index < this.data.length; index++) {
      if (this.data[index]) {
        for (let subIndex = 0; subIndex < this.data[index].length; subIndex++) {
          keys.push(this.data[index][subIndex][0]);
        }
      }
    }
    return keys;
  }
}


delete element by key

  remove(key){
        const address = this.hashMethod(key);
        const currentBucket = this.data[address];
        if(currentBucket){
            for(let i = 0; i <  currentBucket.length; i++){
                if(currentBucket[i][0] === key ){
                    const deleteValue = currentBucket[i];
                    this.data[address].splice(i, 1);
                    return deleteValue;
                }
            }
        }
        return undefined;
    }

el get all keys

  getKeys(){
        const listKeys = [];
        this.data.map((item) => {
            for(let i = 0; i < item.length; i++){
                listKeys.push(item[i][0])
            }
        });
        return listKeys;
    }