How to properly filtered keys object - javascript

I have some objects stored in the localstorage and i want some of it to be ignored when i get the keys, i have an array to filter the keys i want to be ignored. Think of l here as the localstorage with the actual key/value, i want to ignore the bglist ,username and visitedbefore properties, i am trying to do that through looping. But only the bglist is being treated as filtered.
var l = {
'1': [{ description: 'ga', set_title: 'name this reminder' }],
bglist: [
{
author: 'Bildermeines',
images: [
'./images/bildermeines/landscape-2130844.jpg',
'./images/bildermeines/milky-way-2076251.jpg',
'./images/bildermeines/nature-2484584.jpg',
'./images/bildermeines/port-2506025.jpg',
'./images/bildermeines/waterfall-2115206.jpg',
],
},
{
author: 'Jez Timms',
images: [
'./images/jeztimms/jez-timms-157465.jpg',
'./images/jeztimms/jez-timms-158151.jpg',
'./images/jeztimms/jez-timms-178355.jpg',
],
},
{
author: 'Lubos Houska',
images: [
'./images/luboshouska/city-1134141.jpg',
'./images/luboshouska/prague-1168302.jpg',
],
},
{
author: 'oadtz',
images: [
'./images/oadtz/bangkok-1897718.jpg',
'./images/oadtz/electricity-1835546.jpg',
'./images/oadtz/star-1908593.jpg',
],
},
{
author: 'quangle',
images: [
'./images/quangle/ham-ninh-1050828.jpg',
'./images/quangle/sunrise-1014711.jpg',
],
},
{
author: 'skeeze',
images: [
'./images/skeeze/eiffel-tower-1156146.jpg',
'./images/skeeze/monument-valley-1593318.jpg',
'./images/skeeze/mountains-2228259.jpg',
],
},
],
username: 'Disgusting',
visitedbefore: false,
};
let filterArr = ['bglist', 'username', 'visitedbefore'];
let keys = Object.keys(l),
i = 0,
key,
array,
filterItem = 0;
for (; filterItem < filterArr.length; filterItem++) {
for (; (key = keys[i]); i++) {
if (filterArr[filterItem] === key) {
console.log(key + ' is filtered ' + filterArr[filterItem]);
} else {
console.log(key + ' is not filtered');
}
}
}
The following gives me an output
1 is not filtered
bglist is filtered bglist
username is not filtered
visitedbefore is not filtered

The JSON.parse() retriever can be used to easily filter the key value pairs:
var j = '{"1":[{"description":"ga","set_title":"name this reminder"}],"bglist":[{"author":"Bildermeines","images":["./images/bildermeines/landscape-2130844.jpg","./images/bildermeines/milky-way-2076251.jpg","./images/bildermeines/nature-2484584.jpg","./images/bildermeines/port-2506025.jpg","./images/bildermeines/waterfall-2115206.jpg"]},{"author":"Jez Timms","images":["./images/jeztimms/jez-timms-157465.jpg","./images/jeztimms/jez-timms-158151.jpg","./images/jeztimms/jez-timms-178355.jpg"]},{"author":"Lubos Houska","images":["./images/luboshouska/city-1134141.jpg","./images/luboshouska/prague-1168302.jpg"]},{"author":"oadtz","images":["./images/oadtz/bangkok-1897718.jpg","./images/oadtz/electricity-1835546.jpg","./images/oadtz/star-1908593.jpg"]},{"author":"quangle","images":["./images/quangle/ham-ninh-1050828.jpg","./images/quangle/sunrise-1014711.jpg"]},{"author":"skeeze","images":["./images/skeeze/eiffel-tower-1156146.jpg","./images/skeeze/monument-valley-1593318.jpg","./images/skeeze/mountains-2228259.jpg"]}],"username":"Disgusting","visitedbefore":false}'
let filters = { 'bglist': 1, 'username': 1, 'visitedbefore': 1 }
var result = JSON.parse(j, (k, v) => filters[k] ? void 0 : v)
console.log(result)

Related

Merge array of arrays based sub array index as keys (NodeJS/Javascript)

How to write a code that would merge my list in the following way? Performance is important. I want to convert the following array:
"list": [
[
"marketing",
"page_sections",
"PageOne"
],
[
"marketing",
"page_sections",
"PageTwo"
],
[
"webapp",
"page",
"pageone"
],
[
"webapp",
"page",
"pagetwo"
],
To the following format:
[
{
name: "marketing",
path: "marketing/",
children: [
{
name: "page_sections",
path: "marketing/page_sections",
children: [
{
name: "pageOne",
path: "marketing/page_sections/pageOne",
children: []
},
{
name: "pageTwo",
path: "marketing/page_sections/pageTwo",
children: []
},
}
],
},
{
name: "webapp",
path: "webapp/"
children: [
{
name: "page",
path: "webapp/page/"
children: [
{
name: "pageone",
path: "webapp/page/pageone"
children: []
},
{
name: "pagetwo",
path: "webapp/page/pagetwo"
children: []
},
}
]
},
]
The first index of sub array is parent, second index is child of parent, third index is child of second index (and so on).
The shortest approach is to iterate the nested names and look for an object with the same name. If not exist, create a new object. Return the children array as new level.
This approach features Array#reduce for iterating the outer array of data and for all inner arrays.
const
data = [["marketing", "page_sections", "PageOne"], ["marketing", "page_sections", "PageTwo"], ["webapp", "page", "pageone"], ["webapp", "page", "pagetwo"]],
result = data.reduce((r, names) => {
names.reduce((level, name, i, values) => {
let temp = level.find(q => q.name === name),
path = values.slice(0, i + 1).join('/') + (i ? '' : '/');
if (!temp) level.push(temp = { name, path, children: [] });
return temp.children;
}, r);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Looking at the source, and your expected result.
What I would do is loop the list, and then do another loop inside the list. Mix this with Array.find..
Eg..
const data = {list:[
["marketing","page_sections","PageOne"],
["marketing","page_sections","PageTwo"],
["webapp","page","pageone"],
["webapp","page","pagetwo"]]};
function makeTree(src) {
const root = [];
for (const s of src) {
let r = root;
let path = '';
for (const name of s) {
path += `${name}/`;
let f = r.find(k => k.name === name);
if (!f) r.push(f = {name, path, children: []});
r = f.children;
}
}
return root;
}
console.log(makeTree(data.list));
.as-console-wrapper {
min-height: 100%;
}
You can do the following,
list= [
[
"marketing",
"page_sections",
"PageOne"
],
[
"marketing",
"page_sections",
"PageTwo"
],
[
"webapp",
"page",
"pageone"
],
[
"webapp",
"page",
"pagetwo"
],
];
getChildrenItem = (arr) => {
if(arr.length === 1) {
return { name: arr[0], children: []};
} else {
return { name: arr.splice(0,1)[0], children: [getChildrenItem([...arr])]};
}
}
merge = (srcArr, newObj) => {
const {name, children} = newObj;
let index = srcArr.findIndex(item => item.name === name);
if( index> -1) {
children.forEach(item => merge(srcArr[index].children, item))
return ;
} else {
srcArr.push(newObj);
return;
}
}
allObj = [];
list.forEach(item => {
let tempObj = getChildrenItem([...item]);
merge(allObj, tempObj);
});
console.log(allObj);
If Performance is an issue, I think this is one of the best solutions.
let list = [
["marketing", "page_sections", "PageOne"],
["marketing", "page_sections", "PageTwo"],
["webapp", "page", "pageone"],
["webapp", "page", "pagetwo"],
];
const dt = {};
const pushToOBJ = (Object, name) => {
if (Object[name]) return Object[name];
Object[name] = {
name,
children: {},
};
return Object[name];
};
for (let i = 0; i < list.length; i++) {
let subArray = list[i];
let st = pushToOBJ(dt, subArray[0]);
for (let j = 1; j < subArray.length; j++) {
st = pushToOBJ(st.children, subArray[j]);
}
}
let result = [];
const convertObjToChildArray = (obj) => {
if (obj === {}) return [];
let arr = Object.values(obj);
for (let i = 0; i < arr.length; i++) {
arr[i].children = convertObjToChildArray(arr[i].children);
}
return arr;
};
result = convertObjToChildArray(dt);
console.log(result);
No Use of JS find function, which already has O(n) Complexity.

Create unique values from duplicates in Javascript array of objects

I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);

How can I merge object values if they have the same key?

I have an Array full of transactions and I want to divide it by day. It will be an array of date that is and array of transations. It may be a little messy but I want to return this structure.
What I tried to do returns me the structure I want, but I don't know how to merge duplicated key values.
This is the array
const transactions = [
{
name: "Salário",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "1000",
},
{
name: "Pagamento ",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "2350",
},
{
name: "Passagem no VEM",
paidDate: "2020-05-02T00:00:00.000Z",
value: "130",
},
{
name: "Almoço",
paidDate: "2020-05-08T00:00:00.000Z",
value: "50",
},
];
This is what I already tried by now
const days = [];
const finalArray = [];
for (let i = 0; i < transactions.length; i++) {
transactions[i].day = transactions[i].receiveDate || transactions[i].paidDate;
days.push(transactions[i].day);
}
const datesToMatch = [...new Set(days)].map((date) => {
return { [date]: null };
});
transactions.map((transaction) => {
datesToMatch.map((dayObject) => {
const day = Object.keys(dayObject).toString();
if (day === transaction.day) {
finalArray.push({ [day]: [transaction] });
}
});
});
The output
[ { '2020-05-12T00:00:00.000Z': [ [Object] ] },
{ '2020-05-12T00:00:00.000Z': [ [Object] ] },
{ '2020-05-02T00:00:00.000Z': [ [Object] ] },
{ '2020-05-08T00:00:00.000Z': [ [Object] ] } ]
Expected output
[ { '2020-05-12T00:00:00.000Z': [ [Object, Object] ] },
{ '2020-05-02T00:00:00.000Z': [ [Object] ] },
{ '2020-05-08T00:00:00.000Z': [ [Object] ] } ]
Thanks!
Explanation:
dates : extract dates from both fields
uniqueDates : build a Set and convert it into an array so it only has uniqueDates
dateToTransactions : map every unique date to an object with one key (itself) and filter every transaction that is equal to it.
const transactions = [{
name: "Salário",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "1000",
},
{
name: "Pagamento ",
receiveDate: "2020-05-12T00:00:00.000Z",
value: "2350",
},
{
name: "Passagem no VEM",
paidDate: "2020-05-02T00:00:00.000Z",
value: "130",
},
{
name: "Almoço",
paidDate: "2020-05-08T00:00:00.000Z",
value: "50",
},
];
const dates = transactions.map(x => {
const received = x.receiveDate || [];
const paid = x.paidDate || [];
return received + paid;
});
const uniqueDates = [...new Set(dates)];
const dateToTransactions =
uniqueDates.map(
date => {
sameDate = transactions.filter(x => x.receiveDate === date || x.paidDate == date);
return {[date]: sameDate};
});
console.log(dateToTransactions);
I would do something like this:
const days = [];
for (let i = 0; i < transactions.length; i++) {
transactions[i].day = transactions[i].receiveDate || transactions[i].paidDate;
days.push(transactions[i].day);
}
const result = new Map();
days.forEach((day) => {
result.set(day, [])
});
transactions.forEach((transaction) => {
let r = result.get(transaction.day);
r.push(transaction);
result.set(transaction.day, r);
});
Then, in the result map you have a list of the transactions that were made for each day.
This will give the result you expect
const days = {};
const finalArray = transactions.forEach((transaction) => {
let date = (transaction.receiveDate || transaction.paidDate)
if (!days[date]) { days[date] = [transaction]}
else {days[date].push(transaction)}
});
console.log(days);

Finding objects in a nested array along with their position

I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!
Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});
function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps
Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);
Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}
Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript Fill array with missing object and value

I have an array like bellow each index contains different set of objects,I want to create an uniformal data where object missing in each index will with Value:0 ,
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
how can I get an array like bellow using above above array
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
{axis:"Sending Money",value:0,id:6},
{axis:"Other",value:0,id:7},
],
[
{axis:"Email",value:0,id:1},
{axis:"Social Networks",value:0,id:2},
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
]
];
There are two functions:
getAllEntries that find all objects and stores them into a variable accEntries. Then accEntries is used to search for all occurrences in a sub-array of d. This whole process is done in checkArray.
checkArray is used to fetch all found and not-found entries in d. Both Arrays (found and not-found) are then used to build a new sub-array that contains either found entries with certain values and/or not-found entries with values of 0.
Hope this helps:
var d = [
[
{
axis: 'Email',
value: 59,
id: 1
},
{
axis: 'Social Networks',
value: 56,
id: 2
},
],
[
{
axis: 'Sending Money',
value: 18,
id: 6
},
{
axis: 'Other',
value: 15,
id: 7
},
]
];
function getAllEntries(array) {
var uniqueEntries = [];
array.forEach(function (subarray) {
subarray.forEach(function (obj) {
if (uniqueEntries.indexOf(obj) === - 1) uniqueEntries.push(obj);
});
});
return uniqueEntries;
}
function checkArray(array, acceptedEntries) {
var result = [];
array.forEach(function (subArray) {
var subResult = [];
var foundEntries = [];
subArray.forEach(function (obj) {
if (foundEntries.indexOf(obj.axis) === - 1) foundEntries.push(obj.axis);
});
var notFound = acceptedEntries.filter(function (accepted) {
return foundEntries.indexOf(accepted.axis) === - 1;
});
foundEntries.forEach(function (found) {
subArray.forEach(function (obj) {
if (obj.axis === found) subResult.push(obj);
});
});
notFound.forEach(function (notfound, index) {
subResult.push({
axis: notfound.axis,
value: 0,
id: notfound.id
});
});
result.push(subResult);
});
return result;
}
var accEntries = getAllEntries(d);
var result = checkArray(d, accEntries);
console.log(result);
You can loop over the array to find all the unique objects and then again loop over to push the values that are not present comparing with the array of objects of unique keys.
You can use ES6 syntax to find if an object with an attribute is present like uniKeys.findIndex(obj => obj.axis === val.axis); and the to push with a zero value use the spread syntax like d[index].push({...val, value: 0});
Below is the snippet for the implementation
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2},
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7},
{axis:"Social Networks",value:89,id:2},
]
];
var uniKeys = [];
$.each(d, function(index, item) {
$.each(item, function(idx, val){
const pos = uniKeys.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
uniKeys.push(val);
}
})
})
$.each(d, function(index, item) {
var temp = [];
$.each(uniKeys, function(idx, val){
const pos = item.findIndex(obj => obj.axis === val.axis);
if(pos == - 1) {
d[index].push({...val, value: 0});
}
})
})
console.log(d);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How about a short shallowCopy function (Object.assign is not available in IE) and otherwise less than 10 new lines of code?
var d = [
[
{axis:"Email",value:59,id:1},
{axis:"Social Networks",value:56,id:2}
],
[
{axis:"Sending Money",value:18,id:6},
{axis:"Other",value:15,id:7}
]
];
var newD_0 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
var newD_1 = [shallowCopy(d[0][0]), shallowCopy(d[0][1]), shallowCopy(d[1][0]), shallowCopy(d[1][1])];
newD_0[2].id = 0;
newD_0[3].id = 0;
newD_1[0].id = 0;
newD_1[1].id = 0;
d = [newD_0, newD_1];
function shallowCopy(obj) {
var copy = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = obj[key];
}
}
return copy;
}
console.log(JSON.stringify(d));
RESULT:
[
[
{
"axis":"Email",
"value":59,
"id":1
},
{
"axis":"Social Networks",
"value":56,
"id":2
},
{
"axis":"Sending Money",
"value":18,
"id":0
},
{
"axis":"Other",
"value":15,
"id":0
}
],
[
{
"axis":"Email",
"value":59,
"id":0
},
{
"axis":"Social Networks",
"value":56,
"id":0
},
{
"axis":"Sending Money",
"value":18,
"id":6
},
{
"axis":"Other",
"value":15,
"id":7
}
]
]

Categories

Resources