Mam jedną tablicę zawierającą obiekty, których klucze pasują do innej tablicy obiektów z tymi samymi kluczami, a wartością pierwszego klucza jest indeks miesiąca (0 = styczeń, 1 = luty itd.) a punkty mogą przecinać podział na rok (a:10, a:11, a:0, a:1)

Jednak pierwsza tablica może nie mieć takiej samej liczby obiektów, a wartości klucza jednego obiektu mogą nie istnieć w drugim obiekcie tego samego klucza i odwrotnie.

Zakładając, że obie tablice są już poprawnie uporządkowane, chcę porównać te dwie tablice, a jeśli w jednej tablicy brakuje obiektu z wartością klucza, który ma druga, chcę dodać nowy obiekt do pierwszej tablicy z tym samym klucz i wartość w tej samej pozycji / indeksie w tablicy, która go nie ma, jak w tablicy, która go ma.

let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]

arr1 brakuje obiektów z wartością a równą 10, 11 i 2, które istnieją w arr2, a arr2 brakuje obiektów o wartości a równej 3 i 4, które istnieją w arr1

Chcę na końcu skończyć :

arr1 = [{a:10, b:0},{a:11, b:3},{a:0, b:1},{a:1, b:3},{a:2, b:0},{a:3, b:18},{a:4, b:2}]
arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1},{a:3, b:0},{a:4, b:0}]

Teraz arr1 ma nowe elementy / obiekty dla a:10, a:11 i a:2, podczas gdy arr2 ma nowe pozycje dla a:3 i a:4, z których wszystkie mają b wartość 0;

Próbowałem zaplanować to na papierze, aby logicznie zobaczyć, co zrobię fizycznie, ale po prostu nie mogę się tego obejść, więc odpowiedź „Dla opornych” byłaby naprawdę pomocna. Myślałem, że nauczyłem się wystarczająco dużo, aby być zdolnym do zatrudnienia, ale to naprawdę mnie wkurza, a to tylko dla prostego wykresu liniowego płótna HTML5. Pobieram dane z bazy danych, aby porównać dwie linie na tym samym wykresie, gdzie może nie być danych przez jeden miesiąc dla jednego typu danych, ale jest dla innego typu danych. A dla tych miejsc, które nie istnieją w jednym lub drugim, chcę obniżyć linię do 0 na osi Y, a następnie cofnąć się do następnej wartości. https://github.com/rmgreenstreet/custom- formularze / blob / master / public / javascripts / canvasRender.js

2
R Greenstreet 4 kwiecień 2020, 00:21

4 odpowiedzi

Najlepsza odpowiedź

Posiadanie indeksów tylko miesięcznych nie jest wystarczające do prawidłowego sortowania. Wystarczy dodać trochę informacji o roku i będzie to łatwe. Bez sortowania może to wyglądać tak:

// loop elements of the arr2 with reduce,
// if there is any element in arr1 with the same value of key 'a', 
// result is the same as on the previous step
// if there is no elements of that kind, add new object {'a': arr2['a'], 'b' : 0} into arr1

function newArray (arr1, arr2) {
  return arr2.reduce((result, obj2) => {
    if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
      return result;
    }
    return [...result, {['a'] : obj2['a'], 'b':0}];
  }, arr1)
}
// now you can assign the result of newArray() to new variables
const arr1_ = newArray(arr1, arr2)
const arr2_ = newArray(arr2, arr1)

Ostatnia działająca funkcja OP (po zmianie wartości a na ciąg mm/yyyy):

function equalize(arr1, arr2) {
    let newArr = arr2.reduce(function (result, obj2) {
        if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
            return result;
        }
        return [...result, {'a' : obj2['a'], 'b':0}];
    }, arr1);
    newArr.sort(function (a, b) {
        console.log(`a: ${a}`)
        a = a.x.split('/');
        b = b.x.split('/')
        return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
    });
    return newArr;
};
2
R Greenstreet 4 kwiecień 2020, 08:44

Powinieneś zapętlić pierwszą tablicę i sprawdzić, czy każdy klucz znajduje się w drugiej tablicy. Jeśli tak nie jest, wstaw element za pomocą arr .splice ().

Jeśli wiesz, że obie listy są posortowane, tj. Klucze są uporządkowane, nie możesz również sprawdzać całej tablicy pod kątem nowego klucza.

let j = 0;
for (let i = 0; i < arr1.length; i++) {
  let possiblyMissingKey = arr1[i].a;
  while (arr2[j].a < possiblyMissingKey && j < arr2.length)
    j++;
  if (arr2[j].a != possiblyMissingKey) {
    let itemToInsert = {a:possiblyMissingKey, b:0};
    arr2.splice(j, 0, itemToInsert);
  }
}

Po przejściu przez pierwszą tablicę wykonaj drugą.

0
j3ff 4 kwiecień 2020, 01:10

Oto moje rozwiązanie. Używam lodash do funkcji pomocniczych.

function combineArrays (a, b) {
  Object.keys(b).forEach(function (k) {
    const key = parseInt(k);
    if (!a[key]) {
      a[key] = b[key];
      a[key].b = 0;
    }
  });

  return _.values(a);
}

Działający fragment kodu

// const arr1 = [{ a: 1, b: 1 }, { a: 2, b: 3 }, { a: 4, b: 18 }, { a: 5, b: 2 }];
// const arr2 = [{ a: 2, b: 2 }, { a: 3, b: 4 }, { a: 4, b: 8 }, { a: 6, b: 5 }, { a: 7, b: 1 }];

let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]

const arr1Map = _.keyBy(arr1, 'a');
const arr2Map = _.keyBy(arr2, 'a');

function combineArrays(a1Map, a2Map) {
  const a = _.cloneDeep(a1Map);
  const b = _.cloneDeep(a2Map);

  Object.keys(b).forEach(function(k) {
    const key = parseInt(k);
    if (!a[key]) {
      a[key] = b[key];
      a[key].b = 0;
    }
  });

  return _.values(a);
}

console.log(combineArrays(arr1Map, arr2Map));
console.log(combineArrays(arr2Map, arr1Map));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
0
SpiritOfDragon 3 kwiecień 2020, 22:35

Główną przeszkodą w tym zadaniu jest sprawdzanie obecności elementów o określonych wartościach a. Naiwne proste rozwiązanie wymagałoby iteracji po arr2 dla każdego elementu arr1 i odwrotnie, co czyni go O (n 2 ), tj. Powolnym.

Alternatywne podejście sugeruje użycie obiektów jako map szybkiego wyszukiwania. Chodzi o to, aby odwrócić tablicę na lewą stronę, użyć a jako kluczy i b jako wartości.

let arr1 = [{a:1, b:1},{a:2, b:3},{a:4, b:18},{a:5, b:2}]
let arr2 = [{a:2, b:2},{a:3, b:4},{a:4, b:8},{a:6, b:5},{a:7, b:1}]

// Using objects as lookup maps.
let m1 = {}
let m2 = {}

// Filling the maps.
// The 'a' becomes a key, the 'b' becomes a value.
arr1.forEach(v => m1[v.a] = v.b)
arr2.forEach(v => m2[v.a] = v.b)

// Iterating over the keys of m1, checking if m2 has that key,
// if not - adding it with a value of 0.
for (let f in m1) m2[f] || (m2[f] = 0)

// The same goes for m2 -> m1.
for (let f in m2) m1[f] || (m1[f] = 0)

// At this point both m1 & m2 have all the keys from both arrays without gaps.

let res1 = []
let res2 = []

// Assembling the resulting arrays.
for (let f in m1) res1.push({a: f, b: m1[f]})

for (let f in m2) res2.push({a: f, b: m2[f]})

Przepraszam, że mam skłonność do jednokierunkowych.

1
x1n13y84issmd42 3 kwiecień 2020, 22:18