merging local and server updates - javascript

Need to merge 2 lists of updates, local and server.
Using redux (but it doesn't really matter) i need to refresh the updates list.
const localUpdates = [
{ id: 1, name: 'one', date: 'old' },
{ id: 2, name: 'two', date: 'old' },
{ id: 3, name: 'three', date: 'old' },
];
const serverUpdates = [
{ id: 1, name: 'one', date: 'new' },
{ id: 4, name: 'four', date: 'new' },
];
Desired output:
updates: [
{ id: 1, name: 'one', date: 'new' },
{ id: 2, name: 'two', date: 'old' },
{ id: 3, name: 'three', date: 'old' },
{ id: 4, name: 'four', date: 'new' },
]
Thanks in advance (having brainfreeze looiking at this for the past hour)

You can make use of Array.prototype.reduce followed by Object.values to the concated array in order to perform an update
const localUpdates = [
{ id: 1, name: 'one', date: 'old' },
{ id: 2, name: 'two', date: 'old' },
{ id: 3, name: 'three', date: 'old' },
];
const serverUpdates = [
{ id: 1, name: 'one', date: 'new' },
{ id: 4, name: 'four', date: 'new' },
];
const concatArr = localUpdates.concat(serverUpdates);
// we will be excepting new values for same id
const resObj = concatArr.reduce((acc, item)=> {
acc[item.id] = {...(acc[item.id] || {}), ...item};
return acc;
}, {})
console.log(Object.values(resObj));

create a temporary object, loop over both arrays and add each object's id in the temporay object as key and whole object as value. Objects with same id's will be overwritten. Finally use Object.values to get the merged objects in an array.
const localUpdates = [
{ id: 1, name: 'one', date: 'old' },
{ id: 2, name: 'two', date: 'old' },
{ id: 3, name: 'three', date: 'old' },
];
const serverUpdates = [
{ id: 1, name: 'one', date: 'new' },
{ id: 4, name: 'four', date: 'new' },
];
const obj = {};
localUpdates.forEach(local => (obj[local.id] = local));
serverUpdates.forEach(server => (obj[server.id] = server));
console.log(Object.values(obj));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Getting sub index of the parent collection

i have an parent array of objects
const parent = [{name: 'one', id: 1}, {name: 'two', id: 2}, {name: 'three', id: 3}, {name: 'four', id: 4}, {name: 'five', id: 5}]
i have made sub arrays out of it
const childrenCollection = [[{name: 'one', id: 1}, {name: 'two', id: 2}], [{name: 'three', id: 3}, {name: 'four', id: 4}], [{name: 'five', id: 5}]]
now i am looping through the childrenCollection
childrenCollection.map(childrenSubCollection => {
// find the actual index from the main parent array
const indexOfOne = childrenSubCollection.findIndex(childrenSub => {
return childrenSub[0].id === // ??
})
const indexOfTwo = childrenSubCollection.findIndex(childrenSub => {
return childrenSub[1].id === // ??
})
console.log(childrenSubCollection[0], childrenSubCollection[1], 'index', indexOfOne, indexOfTwo )
})
How can i find the index of each from parent array
Using Array#findIndex:
const
parent = [ { name: 'one', id: 1 }, { name: 'two', id: 2 }, { name: 'three', id: 3 }, { name: 'four', id: 4 }, { name: 'five', id: 5 } ],
childrenCollection = [
[ { name: 'one', id: 1 }, { name: 'two', id: 2 } ],
[ { name: 'three', id: 3 }, { name: 'four', id: 4 } ],
[ { name: 'five', id: 5 } ]
];
childrenCollection.forEach(([ one, two ]) => {
const indexOfOne = one ? parent.findIndex(item => one.id === item.id) : -1;
const indexOfTwo = two ? parent.findIndex(item => two.id === item.id) : -1;
console.log(one, two, 'index', indexOfOne, indexOfTwo);
});
Using Map:
const
parent = [ { name: 'one', id: 1 }, { name: 'two', id: 2 }, { name: 'three', id: 3 }, { name: 'four', id: 4 }, { name: 'five', id: 5 } ],
childrenCollection = [
[ { name: 'one', id: 1 }, { name: 'two', id: 2 } ],
[ { name: 'three', id: 3 }, { name: 'four', id: 4 } ],
[ { name: 'five', id: 5 } ]
];
const indexMap = new Map( parent.map(({ id }, index) => ([ id, index ])) );
childrenCollection.forEach(([ one, two ]) => {
const indexOfOne = one ? indexMap.get(one.id) : -1;
const indexOfTwo = two ? indexMap.get(two.id) : -1;
console.log(one, two, 'index', indexOfOne, indexOfTwo);
});

comparing objects in useState and if there is object with same id keep one of them

i'm react beginner, for some reason when i console log i get two japans any advices ?
these are my data:
options initial value (comes from props) is:
[{ id: 1, name: 'Japan' },{ id: 4, name: 'Australia' }, { id: 5, name: 'Poland' }];
and from redux i'm getting this:
[{ id: 1, name: 'Japan' }, { id: 2, name: 'America' }, { id: 3, name: 'Sweden' }];
but my expected out put is :
[{ id: 1, name: 'Japan' },{ id: 4, name: 'Australia' }, { id: 5, name: 'Poland' }, { id: 2, name: 'America' }, { id: 3, name: 'Sweden' }]
const getUnselectedValues = useSelector(UnselectedValues);
const [options, setOptions] = useState(
props.selectedValues
? (
[...props.selectedValues, ...getUnselectedValues]
).filter((e ) => e)
: [...getUnselectedValues]
);
console.log('options:', options)
Try it:
const [options, setOptions] = useState(
props.selectedValues
? Object.values([...props.selectedValues, ...getUnselectedValues].reduce((acc, {id, name}) =>(acc[id] ??= {id, name}, acc),{}))
: [...getUnselectedValues]
);
Approach:
Iterate through the merged array and build a dictionary by using reduce() where the key is the id and the value is {id, value}
In every iteration look up in the dictionary whether has the key in it or not. If the key is not present that means it's a unique entry and inserts it. If the key is already in the dictionary that means the entry is not unique so no need to insert it again.
Here is an example in Vanilla JS so you can play around:
const selectedValues = [{ id: 1, name: 'Japan' },{ id: 4, name: 'Australia' }, { id: 5, name: 'Poland' }];
const getUnselectedValues = [{ id: 1, name: 'Japan' }, { id: 2, name: 'America' }, { id: 3, name: 'Sweden' }];
const res = Object.values([...selectedValues, ...getUnselectedValues].reduce((acc, {id, name}) =>(acc[id] ??= {id, name}, acc),{}));
console.log(res);
Using filter():
const selectedValues = [{ id: 1, name: 'Japan' },{ id: 4, name: 'Australia' }, { id: 5, name: 'Poland' }];
const getUnselectedValues = [{ id: 1, name: 'Japan' }, { id: 2, name: 'America' }, { id: 3, name: 'Sweden' }];
const res = [...selectedValues, ...getUnselectedValues.filter(({id, name}) => !selectedValues.find(it => it.id === id))];
console.log(res);

Trying to get full results using DayJs

I'm trying to get the full results of this code execution, Right now what I get is only the date's of all values, but I need it so that all columns are displayed, so name and date. Can anyone help?
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-23T22:00:00.000Z' }
]
let time = dayjs().format('YYYY-MM-DD')
let eyy = result.filter(item1 => !result.find(item2 => item1.name == item2.name && dayjs(item2.date).format('YYYY-MM-DD') == time))
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
The result.filter method can be simplified by removing the use of result.find, for example...
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-23T22:00:00.000Z' }
]
let time = dayjs().format('YYYY-MM-DD')
let eyy = result.filter(item => dayjs(item.date).format('YYYY-MM-DD') === time)
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>
It's probably worth noting that depending where you are in the world the above will most likely not return anything because there are no dates matching today's date (May 24th).
From your comments it appears you want to modify the structure of the filtered results. To do this you can use the .map() method...
const result = [
{ id: 1, name: 'Tom', date: '2022-05-17T22:00:00.000Z' },
{ id: 2, name: 'Joe', date: '2022-05-12T22:00:00.000Z' },
{ id: 3, name: 'Frederiko', date: '2022-05-23T22:00:00.000Z' },
{ id: 4, name: 'John', date: null },
{ id: 5, name: 'Boer', date: '2022-05-24T22:00:00.000Z' }
];
let time = dayjs().format('YYYY-MM-DD');
let eyy = result.map(item => {
return {
name: item.name,
date: dayjs(item.date).format('YYYY-MM-DD')
};
});
eyy = eyy.filter(item => item.date === time);
console.log(eyy);
<script src="https://unpkg.com/dayjs#1.8.21/dayjs.min.js"></script>

JavaScript search Object Array and return index of parent

I have been looking around for a JavaScript method to return the index of a value but I can't seem to find one that works.
I have the following code:
let topics = [
{
id: 1,
name: 'Topic 1',
children: [
{
id: 2,
name: 'Subtopic 1.1' <---- Searching for this value
}
]
}
];
Is there a method to use on the topics variable to search through the entire object array at once for the value of Subtopic 1.1 and then return the parent index, which in this case would be 0.
There isn't a single function, but you can nest an Array.prototype.find function inside an Array.prototype.findIndex without issue to achieve what you want (findIndex to search through the parents, find to search through the children):
let topics = [{
id: 1,
name: 'Topic 1',
children: [{
id: 2,
name: 'Subtopic 1.1' // <---- Searching for this value
}]
},
{
id: 2,
name: 'Topic 6',
children: [{
id: 5,
name: 'Subtopic 1.7'
}]
},
{
id: 3,
name: 'Topic 9',
children: [{
id: 4,
name: 'Subtopic 1.192'
},
{
id: 28,
name: 'Subtopic 999'
}],
},
];
function findParentIndex(name) {
return topics.findIndex(topic => topic.children.find(child => child.name === name));
}
console.log(findParentId("Subtopic 1.192")); // 3
console.log(findParentId("Subtopic 1.1")); // 1
console.log(findParentId("Not in the list")); // -1
You can use array.findIndex()
let topics = [{
id: 1,
name: 'Topic 1',
children: [{
id: 1,name: 'Subtopic 1.2'
}, {
id: 4,name: 'Subtopic 1.4'
}, {
id: 2, name: 'Subtopic 1.1'
}]
}];
const findIndexOf = val => {
return topics[0].children.findIndex(e => e.name.trim() === val.trim())
}
console.log(findIndexOf('Subtopic 1.1'))
No.
You would iterate through children, then have a nested loop iterating through each index value. If you find a match, the incrementing variable from the parent loop is the index you want.
edit: code example
let topics = [
{
id: 1,
name: 'Topic 1',
children: [
{
id: 2,
name: 'Subtopic 1.1'
},
{
id: 2,
name: 'Subtopic 3.1'
},
{
id: 2,
name: 'Subtopic 1.1'
},
{
id: 2,
name: 'Subtopic 2.1'
},
{
id: 2,
name: 'Subtopic 1.1'
}
]
}
];
for (let i in topics[0]["children"]) {
if (topics[0]["children"][i]["name"] == "Subtopic 1.1") {
console.log(i)
}
}

Get property of first objects in two arrays

I have two array of objects:
var books = [
{ id: 1, name: 'Book A' },
{ id: 2, name: 'Book B' }
];
var cars = [
{ id: 1, name: 'Car A' },
{ id: 2, name: 'Car B' },
{ id: 3, name: 'Car C' },
];
I need to create an array of strings that contains:
1. The Name of the first Book in books (if there are any)
2. The Names of the first 2 Cars in cars (if there are any)
I can do:
if (books.length > 0)
var bookA = books[0].name;
or:
if (cars.length > 1) {
var carA = cars[0].name;
var carB = cars[1].name;
}
Then build the string array but I believe there might be a better way to do this.
Can use filter() and map()
var books = [
{ id: 1, name: 'Book A' },
{ id: 2, name: 'Book B' }
];
var cars = [
{ id: 1, name: 'Car A' },
{ id: 2, name: 'Car B' },
{ id: 3, name: 'Car C' }
];
var res = [books[0], cars[0], cars[1]]
.filter(e => e)// remove undefined's
.map(({name:n}) => n)
console.log(res)
If you are using ES6. You can use [...array1,...array2] to merge them. So I slice the first item in book and use map to get a new array with only string name, and map it to result array.
For the cars array I slice the first two cars and do the same
var resultArray =[];
var books = [
{ id: 1, name: 'Book A' },
{ id: 2, name: 'Book B' }
];
var cars = [
{ id: 1, name: 'Car A' },
{ id: 2, name: 'Car B' },
{ id: 3, name: 'Car C' }
];
resultArray = [...resultArray, ...books.slice(0,1).map(v => v.name)]
resultArray = [...resultArray, ...cars.slice(0,2).map(v => v.name)]
console.log(resultArray)
One of a million ways to do it. This one would allow you to easily create a data structure (arrayDefinition) that configures what property to get from which array and at which index, which you could e.g. retrieve from a RESTful webservice.
var books = [
{ id: 1, name: 'Book A' },
{ id: 2, name: 'Book B' }
];
var cars = [
{ id: 1, name: 'Car A' },
{ id: 2, name: 'Car B' },
{ id: 3, name: 'Car C' },
];
const arrayDefinition = [
{
source: 'books',
index: 0,
prop: 'name'
},
{
source: 'cars',
index: 0,
prop: 'name'
},
{
source: 'cars',
index: 1,
prop: 'name'
}
];
let resultArr = []
arrayDefinition.forEach(function(def) {
if (Array.isArray(window[def.source]) && window[def.source].length >= def.index) {
resultArr.push(window[def.source][def.index][def.prop])
}
})
console.log(resultArr)

Categories