Je travaille en Javascript et crée une application hors ligne.

J'ai un très grand tableau, plus de 10 Mo. J'ai besoin de sauvegarder des éléments du tableau où un utilisateur a effectué un changement, mais l'écriture / lecture du tableau sur le disque est trop lente.

Je voudrais créer un deuxième tableau qui ne contient que les modifications apportées par l'utilisateur, afin que je puisse enregistrer ce tableau plus petit, puis lorsque je dois charger des modifications, il peut refléter ses modifications dans le grand tableau.

Par exemple:

lib[x][1][y][6] = "no";
libVars[x][1][y][6] = "no";

LibVars contiendrait simplement les changements d'élément dans lib et n'aurait pas la même taille que le grand tableau lib car l'utilisateur n'interagirait qu'avec une petite partie du grand tableau.

Évidemment, cela ne fonctionne pas, car libVars n'a pas la même structure que lib, et s'il le faisait, cela prendrait également beaucoup de mémoire (je pense que de toute façon!)

Je voudrais ensuite parcourir libVars et mettre à jour lib aux mêmes points d'éléments où les modifications ont été enregistrées dans libVars.

Existe-t-il un moyen d'enregistrer un type de pointeur vers un emplacement dans lib que je pourrais stocker dans libVars avec la valeur d'élément associée?

Toute aide serait très appréciée.

Merci.

======================

Échantillon de ma large gamme

var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"] ... 

Tentative de solution publiée par Z-Bone

J'ai ajouté la variable tempLib, mais je ne vois pas comment vous finirez par mettre à jour l'objet lib réel

Object.entries(libVars).forEach(([path, value]) => {

  var tempLib = lib;
  var pathParts = path.split('#');

  pathParts.forEach((pathPart, index) => {

  if (index == pathParts.length-1) {

    tempLib[pathPart] = value;

  } else {
    //I don't fully track what you are doing here. 
    //I assume you are building the array path, but to me it looks like
    // it's getting wiped out and not built upon?    
    tempLib = tempLib [pathPart];
  }
});
});
1
nomaam 27 janv. 2019 à 02:53

4 réponses

Meilleure réponse

Mise à jour 28/01/2019 Basé sur les données de test de nomaam

@nomaam Veuillez vérifier l'extrait suivant. Je lui ai fait changer un chemin arbitraire dans le tableau lib. Le chemin que j'ai choisi est le suivant: lib[0][1][3][4]. Vous pouvez voir comment il renvoie initialement la valeur "no", puis après l'exécution de la solution de suivi des modifications, il renvoie la valeur "yes".

// First Step: Original Data (lib)
var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"]]]]

// Log initial value in arbitrary selection lib[0][1][3][4]
console.log(lib[0][1][3][4])

// Second Step: Pointer's object
var libVars = {}

// Example of changing a value via an artificial "pointer" to lib[0][1][3][4]
libVars['0#1#3#4'] = 'yes'; // original value is "no"

// Third Step: Run the modifier - update changes from libVars to lib
Object.entries(libVars).forEach(([path, value]) => {

  var tempLib = lib;
  var pathParts = path.split('#');
  
  pathParts.forEach((pathPart, index) => {
    
    if (index == pathParts.length - 1) {
      
      tempLib[pathPart] = value;
      
    } else {
      
      tempLib = tempLib[pathPart];
      
    }
  });
});


// Log the change fro lib
console.log(lib[0][1][3][4])

Réponse originale

Si je comprends bien votre défi, vous pourriez techniquement tenir un objet avec le chemin d'accès à la propriété que vous souhaitez modifier comme clé et la valeur modifiée comme valeur.

Disons que votre objet d'origine ressemble à ceci:

var lib = {a: {b: { c: { d: "yes"}}}}

Vous pouvez conserver un journal des modifications dans un objet de sauvegarde (par exemple, les changements de valeur de "oui" à "non"). Cela pourrait ressembler à ceci, avec . marquant une propriété imbriquée.

var libVars = {};
libVars['a.b.c.d'] = "no";

Ensuite, lorsque vous souhaitez mettre à jour le grand tableau / objet de valeurs d'origine, vous pouvez le faire:

Object.entries(libVars).forEach(([path, value]) => {
    var tempLib = lib;
    // split by nesting indicator -> dot
    var pathParts = path.split('.');
    // iterate all parts of the path to the modified value
    pathParts.forEach((pathPart, index) => {
        if (index == pathParts.length-1) {
            // once you made your way to last index, update value
            tempLib[pathPart] = value;
        } else {
            tempLib = tempLib[pathPart];
        }
    })
})

console.log(lib); // outputs => {a: {b:{c: {d : "no"}}}}
2
Z-Bone 28 janv. 2019 à 22:03

En supposant que les chemins d'accès dans libVars sont les mêmes dans lib, vous pouvez simplement enregistrer les modifications dans un tableau de fonctions que vous réappliquez plus tard sur votre objet lib:

const data = {foo: 'aaa', bar: 'bbb'};

console.log('data before:', data);

const updates = [];

updates.push(obj => {
  obj.foo = 'foo';
});

updates.push(obj => {
  obj.bar = 'bar';
});

updates.forEach(fn => fn(data));

console.log('data after:', data);
0
customcommander 27 janv. 2019 à 01:16

Mise à jour 2

Mise à jour de ma réponse, pour se débarrasser de lodash, et elle semblait être égale à la réponse de Z-Bone. Sa variante est encore plus claire que la mienne.

Mis à jour le 28.01.2019

var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"]]]];

// object to track edits
var edits = {
  '0.1.2.2': 'edited'
};

// sample/simple implementation of lodash's 'set' function
function applyEdit(arr, path, value) {
  var items = path.split('.');
  var last = items.length - 1;
  var current = arr;
  items.forEach(function (item, i) {
    if (i !== last) {
      current = current[item];
    }
  });
  current[items[last]] = value;
}

// our restoration function
function patch(arr, edits) {
  Object.keys(edits).forEach(function(key) {
    var newValue = edits[key];
    applyEdit(arr, key, newValue);
  });
}

console.log(lib[0][1][2][2]) // "sample3"

// now we can restore our edits
patch(lib, edits);

console.log(lib[0][1][2][2]) // "edited"

// --------------------------------------------------------

// to prevent forgetting to track the updates you can use utility function
// to make changes to your 'lib' array

function update(arr, path, value) {
  applyEdit(arr, path, value);
  edits[path] = value;
}


Réponse originale:

Une solution possible serait d'avoir un objet où vous suivriez toutes les modifications. const edits = {}; Et lorsque vous mettez à jour votre objet avec lib[x][1][y][6] = "no";, vous enregistrez également votre modification:

edits[`${x}.1.${y}.6`] = "no";

Fondamentalement, vous créez simplement une chaîne contenant le chemin du changement.

Après avoir chargé votre objet de modifications à partir d'un fichier, vous pouvez appliquer toutes les modifications au tableau d'origine avec le code suivant:

import { set } from 'lodash';

function patch(arr, edits) {
  Object.keys(edits).forEach(key => {
    const newValue = edits[key];
    set(arr, key, newValue);
  });
}
1
quadreex 28 janv. 2019 à 23:44

Cela peut être géré avec une autovivification émulée à l'aide de Proxy. Voir:

https://en.wikipedia.org/wiki/Autovivification

Autovivification et Javascript

0
vsemozhetbyt 27 janv. 2019 à 01:23