Swapping two objects by changing the result in JavaScript

1

I have two objects, and I want to return them permuted in JavaScript , that is, if I enter a and b as arguments, I return [b,a] , changing the order .

But I do not want a function that only returns the permuted result, but also that I change the values of the objects (they can also be arrays) entered.

In the following code, none of the two functions permutar serves. The first does not, because it does not change the values, and only returns the permuted values. The second does not either, because although it returns the permuted values, it only changes the values within the function, but on the outside they remain the same:

var funciones_permutar=[
  function permutar(a,b)
  {
      return [b,a]
  },
  function permutar(a,b)
  {
    var c=a
    a=b
    b=c
    return [a,b]
  }
]
for(var i=0;i<funciones_permutar.length;i++)
{
  var objeto_1={d:2,e:3}
  var objeto_2={f:4}
  
  console.log("Función permutar "+(i+1))

  //Devuelve correctamente.
  console.log(JSON.stringify([objeto_1,objeto_2]))
  console.log(JSON.stringify(funciones_permutar[i](objeto_1,objeto_2)))

  //Devuelve [{"d":2,"e":3},{"f":4}], pero debería devolver [{"f":4},{"d":2,"e":3}]
  console.log(JSON.stringify([objeto_1,objeto_2]))
}
    
asked by ArtEze 08.07.2017 в 04:38
source

5 answers

1

Introduction

answer, here leave another using this and variable names as keys this in order that the solution is modular, meaning that if the names of the variables change, it is not necessary to change the function. It also makes use of arrow functions .

  

Note: This solution works for global variable, as was stated in the revision 2 question

Two scenarios are presented, two objects of the same type, and two objects of different types, the first being an object {} and the other an array [].

Scenario 1: Two objects of the same type, {}

var objeto_1 = {d: 2,e: 3}
var objeto_2 = {f: 4}

/*
 * Intercambia la asignación de objetos a dos variables y devuelve una 
 * arreglo (array) con los objetos permutados
 *
 * @param {String} a nombre de la primer variable
 * @param {String} b nombre de la segunda variable
 *
 * @returns {Array}    
 */

function permutar(a, b) {

  // Intercambiar asignación de objetos entre dos variables
  var swap = x => x;
  this[a] = swap(this[b],this[b]=this[a])

  // Devolver los objetos permutados en una matriz
  return [this[a],this[b]];
}

console.log("--- valores originales ---");
console.log(JSON.stringify([objeto_1, objeto_2]));

/* Llamar la función solución y asignar resultado a variable */
var permuta = permutar("objeto_1", "objeto_2");
console.log("--- resultado de la función solución ---");
console.log(JSON.stringify(permuta));

console.log("--- verificación de intercambio ---")
console.log(JSON.stringify([objeto_1, objeto_2]));

Scenario 2: Two objects of different type, one object {} and one matrix []

var objeto_1 = {d: 2,e: 3}
var matriz_1 = [4]

/*
 * Intercambia la asignación de objetos a dos variables y devuelve una 
 * arreglo (array) con los objetos permutados
 *
 * @param {String} a nombre de la primer variable
 * @param {String} b nombre de la segunda variable
 *
 * @returns {Array}    
 */

function permutar(a, b) {

  // Intercambiar asignación de objetos entre dos variables
  var swap = x => x;
  this[a] = swap(this[b],this[b]=this[a])

  // Devolver los objetos permutados en una matriz
  return [this[a],this[b]];
}

console.log("--- valores originales ---");
console.log(JSON.stringify([objeto_1, matriz_1]));

/* Llamar la función solución y asignar resultado a variable */
var permuta = permutar("objeto_1", "matriz_1");
console.log("--- resultado de la función solución ---");
console.log(JSON.stringify(permuta));

console.log("--- verificación de intercambio ---")
console.log(JSON.stringify([objeto_1, matriz_1]));

Explanation

this is a JavaScript keyword that changes its behavior according to the context and as it is called. In this case, when using the name of the variables as a key, the global variable with that name is called.

swap is a variable that has been assigned an arrow function that returns the object received as an argument. This type of function has been preferred for its brevity.

Reference

Answer to Swap two objects in JavaScript

Related questions

answered by 08.07.2017 / 22:05
source
2
  • In JavaScript the variables refer to objects
  • If we want to change the object to which a variable refers, we must use the name of that variable in the assignment of the object.
  • Example:

    var objeto_1 = {
      d: 2,
      e: 3
    }
    var objeto_2 = {
      f: 4
    }
    
    // Cambia el orden de los objetos y los devuelve como una arreglo (array)
    function permutar(a, b) {
      var permuta = [b, a];
      // Para asignar un objeto a una variable debemos usar el nombre de la 
      // variable en cuestión
      objeto_1 = permuta[0];
      objeto_2 = permuta[1];
      return permuta;
    }
    
    console.log(JSON.stringify([objeto_1, objeto_2]));
    var permuta = permutar(objeto_1, objeto_2);
    console.log(JSON.stringify(permuta));
    
    
    console.log(JSON.stringify([objeto_1, objeto_2]));
        
    answered by 08.07.2017 в 07:21
    2

    Explanation

    I explain what happens behind the scenes

    ;(function()
    {
    "use strict"
    
    function intercambiar(a,b)
    {
        var c = a // ok
        a = b // mal
        b = c // mal
    }   
    
    }())
    

    Doing a = b equals making var a = b is now the variable LOCAL a points to b , the same happens with the other line b = c equals making var b = c , the Previous code can be re-written as

    ;(function()
    {
    "use strict"
    
    function intercambiar(a,b)
    {
        var a  // esto es redudante
        var b  // esto es redudante
    
        var c = a // ok
        a = b  
        b = c
    }   
    
    }())
    

    The first two lines are redudantes, since they are done automatically when calling a function, however when viewing it in this way we can easily visualize that both a as b , are variable LOCALES .

    Alternatives

    In javascript everything is an object, even contextos it is normal to create a space where we can place variables and permute them, by default the global space in browsers is window however in nodejs the global space is global

    ;(function()
    {
    "use strict"
    
    function intercambiar(contexto, var1, var2)
    {
    	var aux = contexto[var1]
    	contexto[var1] = contexto[var2]
    	contexto[var2] = aux
    	return [contexto[var1], aux]
    }	
    
    var global = {} // nuestro contexto
    global.a = "foo"
    global.b = "bar"
    
    console.log(global) // {a: "foo", b: "bar"}
    console.log(intercambiar(global, "a", "b")) // [bar, foo]
    console.log(global) // {a: "bar", b: "foo"}
    }())

    As you can see it is very simple, I hope I have clarified the doubts

    A rough and rough solution is the following

    function intercambiar(a,b)
    {
        var aux = this[a]
        this[a] = this[b]
        this[b] = aux
        return [this[a], aux]
    }
    
    var a = {clave : 1234}
    var b = ["hola" , "mundo"]
    console.log([a,b])
    console.log(intercambiar("a","b"))
    console.log([a,b])

    An inefficient, gross and crude form

    Object.prototype.encontrar = function(valor)
    {
      for (var clave in this)
        {
          if (this[clave] == valor) { return clave }
        }
      return undefined
    }
    
    function permutar(a,b)
    {
      var a = this.encontrar(a)
      var b = this.encontrar(b)
      if(!a || !b) { return [] }
    
      var aux = this[a]
      this[a] = this[b]
      this[b] = aux
    
      return [this[a], aux]
    }
    
    var a = {clave: 1123}
    var b = ["hola", "mundo"]
    
    console.log([a,b])
    console.log(permutar(a,b))
    console.log([a,b])
    

    Note: the previous code does not work in the stackoverflow embedded console, to try it you must do it directly in the browser

        
    answered by 08.07.2017 в 05:34
    1
      

    There are two possible scenarios, one is that you want to exchange objects of the same type of data, that is, two arrays, or two objects. The other scenario is that you want to permute two objects of different types, that is, an object and an array, or an array and an object.

    If you want to swap objects with different data types , it is not possible to do it completely well, but if you want to swap objects with the same type of data , you can do correctly. This is because it is not possible to change the data type of an array to an object, that is, an array will always be an array , and not an object. In other words, an length property can not be removed from an array.

    The permutation function that I propose, what it does is the following:

  • Copy the two objects (reference no) to permute.
    • Since it is not possible to copy it exactly, it is done in the best possible way. That is, to dump all the properties of an object to a new one.
    • Determine if it is an array, using the same object, or an auxiliary boolean.
    • Returns another object or array depending on the determined.
  • Receives an auxiliary array that determines if the objects to be swapped are objects or arrays.
    • If it is not received, it generates it through the objects entered.
  • For each of the objects entered, proceed as follows:
  • Empty the object.
    • This clears all the properties of the object.
    • Also, it does not delete them only within the function, but when leaving the function, the object should be empty.
    • Depending on whether it is determined as an object or array, you can put length in 0 , or delete that property, since objects should not have it.
  • I have created a function to absorb the data type . What it does is put an object to have the same type of data. If it is not possible, it remains in the auxiliary array.
    • The entered object absorbs the data type of the copy of the other object. The data type is stored in the auxiliary array.
    • In the first iteration, the first object absorbs the copy of the second object.
    • In the second iteration, the second object absorbs the copy of the first object.
    • This changes the values of the auxiliary array, so you can notice the change when exiting the function.
  • Add all the properties of the other object to the object.
    • In the first iteration, add the second iteration to the first.
    • In the second iteration, add the first iteration to the second.
    • As in the previous steps, it also changes the objects so that they are changed outside the function.
  • To the auxiliary array, which previously had 4 elements, two for the copies, and two for the entered objects, it is modified so that it has only two. This means that the first element is true if the second object entered was an array, and the second element is true if the first object was an array. If it is false , it means that they were determined as objects instead of arrays.
    • With this action it happens as in the others, change the array, instead of replacing it with another one.
  • Returns an array with the permuted objects, and also with the auxiliary array.
    • Instead of returning the modified original objects, what it does is show the results, first copying the objects, taking into account the auxiliary array.
    • This is so, since an array converted into an object can not be displayed naturally as an object, and it is necessary to create another object with the adapted characteristics.
  • /*Función que genera un array de cada elemento de un array ingresado:
      Ejemplo: es_array([ [], {}, [] ])
      -> [ true, false, true ]
    */
    function es_array(objetos,son_arrays)
    {
      //Si no existe el array auxiliar ingresado, lo crea.
      if(son_arrays==undefined){son_arrays=[]}
      
      //Determina si es array cada objeto.
      for(var i in objetos){son_arrays.push(Array.isArray(objetos[i]))}
      
      return son_arrays
    }
    
    /*Función que borra todas las propiedades del objeto.
     Ejemplos: [0,1,2,3] -> []
               {a:2,b:3} -> {} */
    function vaciar(objeto,objeto_es_array)
    {
      //Borra las propiedades del objeto ingresado.
      for(var i in objeto){delete objeto[i]}
      
      /*Determina si el objeto necesita la propiedad length dependiendo de
        si es o no un array*/
      if(objeto_es_array){objeto.length=0}else{delete objeto.length}
      
      return objeto
    }
    
    /*Absorbe el tipo de dato del segundo objeto al primero.
     Ejemplos: [] {} -> {} {}
               {} [] -> [] [] */
    function absorber_tipo_de_dato(uno,actual_son_arrays)
    {
      //Asigna a son_arrays el array auxiliar.
      var son_arrays=actual_son_arrays[0]
      
      /*Cambia la propiedad length del primer objeto ingresado dependiendo
        de si el segundo es array. */
      if(son_arrays[actual_son_arrays[2]]){uno.length=0}else{delete uno.length}
      
      /*Cambia al array auxiliar para que los dos valores queden iguales. */
      son_arrays[actual_son_arrays[1]]=son_arrays[actual_son_arrays[2]]
    
      return son_arrays
    }
    
    /*Función que agrega valores al primer objeto mediante una propiedad
      que está en el segundo objeto.
    La funcionalidad es: uno[i]=dos[i] */
    function agregar(uno,dos,i,uno_es_array)
    {
      /*Si el primer objeto es array, la propiedad es un número, y por eso
        aumenta la longitud del array hasta un valor inmediatamente
        mayor a ese número. */
      if(uno_es_array)
      {
        i=+i
        if(uno.length<=i){uno.length=i+1}
      }
      
      /*Asigna la propiedad i al primer objeto, obteniéndola
        desde el segundo objeto. */
      uno[i]=dos[i]
      
      return uno
    }
    
    //Copia todas las propiedades de un objeto a otro nuevo.
    function copiar(objeto,objeto_es_array)
    {
      var copia
      
      //Declara y determina el booleano auxiliar si no existe.
      if(objeto_es_array==undefined){objeto_es_array=es_array([objeto])[0]}
      
      /*Convierte a objeto o array según está determinado
        en el booleano auxiliar. */
      if(objeto_es_array){copia=[]}else{copia={}}
      
      /*Agrega cada propiedad a la copia desde el objeto ingresado. */
      for(var i in objeto){agregar(copia,objeto,i)}
    
      return copia
    }
    
    //Función principal, que permuta los objetos.
    function permutar(uno,dos,son_arrays)
    {
      //Pone los objetos originales junto con sus copias.
      var objetos=[copiar(uno),copiar(dos),uno,dos]
      
      /* Si no existe el array auxiliar lo declara y lo determina. */
      if(son_arrays==undefined)
      {
        //Genera el array auxiliar.
        son_arrays=es_array(objetos)
      }
      else
      {
        if(son_arrays.length==0)
        {
          //Si el array auxiliar está vacío, lo llena.
          es_array(objetos,son_arrays)
        }
        else
        {
          /* Replica los valores del array auxiliar y los pone al final.
            Ejemplo: [false,true] -> [false,true,false,true]
          */
          for(var i=0;i<2;i++){son_arrays.push(son_arrays[i])}
        }
      }
      
      //Itera 2 veces, una para cada objeto ingresado.
      for(var i=0;i<2;i++)
      {
        /* Declara variables, el original, la copia del objeto no actual y
          un array que contiene al array auxiliar junto con las posiciones
          que se quiere cambiar de ese array auxiliar. */
        var original=objetos[i+2]
        var copia=objetos[1-i]
        var actual_son_arrays=[son_arrays,i,1-i]
    
        //Vacía el objeto del objeto de la iteración actual.
        vaciar(original,son_arrays[i+2])
        
        //Absorbe el tipo de dato del objeto actual.
        absorber_tipo_de_dato(original,[son_arrays,i+2,1-i])
        
        /*Agrega todas las propiedades al objeto actual desde
          la copia del objeto no actual. */
        for(var j in copia){agregar(original,copia,j,son_arrays[i+2])}
      }
      
      /*Cambia el array auxiliar para mostrar sus dos últimos valores. */
      for(var i=0;i<2;i++){son_arrays.shift()}
      
      return [copiar(uno,son_arrays[0]),copiar(dos,son_arrays[1]),son_arrays]
    }
    
    //Array auxiliar.
    var son_arrays=[]
    
    //Objetos a permutar.
    var objeto_1={d:2,e:3}
    var objeto_2=[0,1,2,3,4,5]
    
    console.log("Se muestran 3 elementos. Los dos primeros, son los objetos"+
      " a permutar. El último es un array auxiliar con dos booleanos, que"+
      " determinan si cada uno de los objetos resultantes, es un array "+
      "(si es true)."
    )
    console.log("Original: ",
      JSON.stringify([objeto_1,objeto_2,son_arrays]))
    
    console.log("Permutado mostrado correctamente: ",
      JSON.stringify(permutar(objeto_1,objeto_2,son_arrays)))
    
    console.log("Permutado como son realmente: ",
      JSON.stringify([objeto_1,objeto_2,son_arrays]))
        
    answered by 10.07.2017 в 00:23
    -3

    That can only be done in languages that call a function pass (or can pass) arguments by reference (as is the case of C ++). Javascript (like the vast majority of popular languages) passes arguments by value. So no, you can not.

    Of course it is possible if you pass the arguments as an array (in this case you simply invert the values of the array), but I guess that is not what you want. And of course it is also possible if from within the function I can "see" the original variables, but, again, that is trivial.

    Why can not you? We can start thinking like this: suppose that a and b are integers. Can we achieve what we want?

      var a= 1;
      var b= 2;
      permutar(a,b);
      // quiero que de aquí en más a y b tengan sus valores permutados
    
      function permutar(x,y) {
        .... ??
      } 
    

    A little reflection shows that this is not possible. Because when invoking the function the values that have a and b are copied into the local variables x y , and any modification made about x e y will not impact the values of a b .

    The same is true if a and b are objects. Because in Javascript a variable that refers to an object is, precisely, a reference - that we can think of it as a kind of pointer or (better) a "handle": simply a number with which Javascript internally identifies the object. When calling permutar(a,b) what are passed (by copy!) Are those numbers. And nothing that we do with those copies of the references within the function will change the references "from the outside".

        
    answered by 08.07.2017 в 04:52