Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

145
Vistas
Agregar y reducir valores duplicados

Tengo un gráfico de dispersión (usando apexchart) y estoy tratando de preparar mis datos (objetos en una matriz) antes de agregarlos al gráfico.

Mi problema es que a menudo tengo algunos datos que pueden tener exactamente los mismos valores en los ejes x e y. Esto significa que se superpondrán entre sí y solo se mostrará un elemento.

Primero agregué una solución simple usando Math.random() para cada valor duplicado, pero esto significa que se reposicionarán ligeramente cada vez que se actualice el gráfico, lo que confundirá a los usuarios.

Entonces, lo que quiero lograr es agregar la misma "inestabilidad"/cambios para cada elemento todo el tiempo. Así que mi pensamiento es hacerlo así:

 //1. The first three duplicates should add 0.05 to the x value. So it will say: item1.x = 10 //original value item2.x = 10.05 item3.x = 10.1 item4.x = 10.15 //2. Then, If more duplicates than 3, the next 3 should reduce 0.05 of the original value: item5.x = 9.95 item6.x = 9.90 item7.x = 9.85 //If more than 7 items with the same value, then just use the original value.

¿Cómo podría ser la mejor manera de lograr esto? En este momento tengo los valores duplicados y puedo agregar "inestabilidad", pero ¿cómo puedo hacer que siga contando y haga lo que quiero arriba?

Logré filtrar los duplicados, pero luego me quedé atascado:

 const duplicates = AllItems.filter((val, i, self) => self.findIndex(item => item.x == val.x && item.y == val.y) != i);

¿Algunas ideas?

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Creo que vale la pena separar el código que maneja el jitter del código que actualiza los puntos usando ese jitter. Eso le daría la posibilidad de probar diferentes funciones de fluctuación (una espiral de Arquímedes estaría bien), pero aún así mantendría intacta la lógica principal. Aquí hay una versión que hace esto:

 const updatePoints = (jitterAlgo) => (points) => points .reduce (({res, dups}, {x, y}) => { const key = `${x}:${y}` const matches = dups [key] || (dups [key] = []) const val = jitterAlgo (matches .length, {x, y}) matches .push (val) res .push (val) return {res, dups} }, {res: [], dups: {}}) .res const customJitter = (len, {x, y, ...rest}) => len == 0 || len > 6 ? {x, y, ... rest} : len < 3 ? {x: x + len * .05, y, ... rest} : {x: x - len * .05, y, ... rest} const points = [{"x": 1, "y": 6}, {"x": 3, "y": 5}, {"x": 3, "y": 5}, {"x": 5, "y": 4}, {"x": 3, "y": 5}, {"x": 3, "y": 5}, {"x": 3, "y": 5}, {"x": 1, "y": 9}, {"x": 5, "y": 4}, {"x": 5, "y": 4}, {"x": 3, "y": 5}, {"x": 2, "y": 9}, {"x": 3, "y": 5}, {"x": 3, "y": 5}, {"x": 5, "y": 4}, {"x": 2, "y": 8}] console .log (updatePoints (customJitter) (points))
 .as-console-wrapper {max-height: 100% !important; top: 0}

Creo que su lógica actual, que solo se mueve en la dirección x , probablemente no sea tan agradable como la que hace tanto x como y .

about 4 years ago · Juan Pablo Isaza Denunciar

0

Suponiendo tener este vector de entrada:

 coordinates = [{x:1,y:2},{x:1,y:2},{x:10,y:1},{x:1,y:2},{x:10,y:1}]

y este vector de deltas:

 deltas = [0.05,0.1,0.15,-0.05,-0.1,-0.15]

este código recupera los duplicados y luego les agrega los deltas (si hay más de 6 duplicados, agrega 0):

 coordinates.map( (e,i,v) => { ret = !ed ? v.reduce( (acc,d,j) => { if (!dd && j != i && dx === ex && dy === ey) { dd=1 acc.push(d) } return acc }, [] ) : [] ed =1 return ret } ) .filter(e => e.length) .forEach(e => e.forEach((c,i) => cx += deltas[i] || 0))

La propiedad 'd', agregada a los duplicados de seguimiento, se eliminará:

 coordinates.forEach(e => delete ed)

El resultado es:

 coordinates (5) [{…}, {…}, {…}, {…}, {…}] 0: {x: 1, y: 2} 1: {x: 1.05, y: 2} 2: {x: 10, y: 1} 3: {x: 1.1, y: 2} 4: {x: 10.05, y: 1} length: 5
about 4 years ago · Juan Pablo Isaza Denunciar

0

Considere usar Map incorporado. Funciona mejor en este caso, ya que hay frecuentes adiciones y eliminaciones de pares clave-valor.

Dicho esto, vale la pena mencionar que actúa como una implementación de tabla hash. La idea es hacer un seguimiento del número de veces que ocurre una determinada x sumando uno a su count cada vez que encuentre una ocurrencia. Para el ejemplo de points en el fragmento, considere la siguiente tabla de mapa:

 ╔═══════╦═══════════════════════════════╗ ║ x ║ 1 2 3 4 5 6 7 8 9 10 ║ ╠═══════╬═══════════════════════════════╣ ║ count ║ 5 1 1 1 7 1 1 1 1 10 ║ ╚═══════╩═══════════════════════════════╝

Tenga en cuenta que el valor y de los puntos cuya x es 1 no cambiará porque su cuenta es 5. Mientras que 5 y 10 sí lo harán, debido a que su cuenta es mayor o igual que MIN_TIMES (7). La lógica sigue:

  1. Construya el Mapa para almacenar cuántas veces un punto x dado repite su coordenada y .
  2. Almacene cada x solo aquellos que suceden más o igual que MIN_TIMES en la matriz
  3. Al mismo tiempo, cambie el conteo a 0 para comenzar a contar
  4. Asigne cada punto en la matriz de points y convierta aquellos que están en xRepeatedAtLeastMinTimes para aumentar o disminuir, según su lógica.

 const points=[{x:1,y:1},{x:1,y:1},{x:1,y:1},{x:1,y:1},{x:1,y:1},{x:2,y:2},{x:3,y:3},{x:4,y:4},{x:5,y:5},{x:5,y:5},{x:5,y:5},{x:5,y:5},{x:5,y:5},{x:5,y:5},{x:5,y:5},{x:6,y:6},{x:7,y:7},{x:8,y:8},{x:9,y:9},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10},{x:10,y:10}]; const m = new Map(), xRepeatedAtLeastMinTimes = new Array(), INTERVAL = 0.05, MIN_TIMES = 7 // Construct map points.forEach(point => m.set(point.x, m.has(point.x) ? (m.get(point.x) + 1) : 1)) // Get x coordinates that happens at least MIN_TIMES and change its count to 0 for (let [x, count] of m.entries()) count >= MIN_TIMES && xRepeatedAtLeastMinTimes.push(x), m.set(x, 0) // Map each point and check condition based on count stored on Map let result = points.map(point => { let x = point.x if (xRepeatedAtLeastMinTimes.includes(x)) { let count = m.get(x) m.set(x, count + 1) return count === 0 ? point : count <= 3 ? { ...point, x: x + count*INTERVAL } : count <= 6 ? { ...point, x: x - (count - 3)*INTERVAL } : point } return point }) console.log(result)

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda