I have two arrays, slicesRank and slicesCount with following structure. Each element has id and value, which is an array of 46. values is composed of date and measurement.
e.g. sliceRank[0]:
{id: Catan=rank, values(Array(46)) : {date, measurement} }
e.g. sliceCount[0]:
{id: Catan=count, values(Array(46)) : {date, measurement} }
What should I do if I want to combine the elements with the same prefix in id names. For example, the first element in this two arrays.
The desired sturcture would be
{id: Catan, values(Array(46)) : {date, count, rank} }
I tried the following, but the values shows undifined.
for(i=0; i<slicesRank.length; i++) {
var newElement = {};
newElement['id'] = slicesRank[i].id.replace('=rank', '');
newElement['values'] = {
date: slicesRank[i].date,
rank: slicesRank[i].measurement,
count: slicesCount[i].measurement
};
sliceNew.push(newElement);
};
The structure of slicesRank is like this:
Here's a sample transformation that you can try:
const combined = slicesRank.map((rank) => {
const id = rank.id.replace("=rank", "");
const count = slicesCount.find(
(count) => count.id.replace("=count", "") === id
);
return {
id,
values: rank.values.map((val, index) => ({
date: val.date,
rank: val.measurement,
count: count?.values[index].measurement
}))
};
});
Here's a working example
https://codesandbox.io/s/awesome-lovelace-e31zj?file=/src/index.js
By slice I think you mean Array.
const combinedArray = sliceRank.map((sliceItem, itemIndex) => {
return {
id,
values: sliceItem.values.map(({ date, measurement }, valueIndex) => ({
date,
count: sliceCount[itemIndex][valueIndex].measurement,
rank: measurement,
}))
}
})
This solution returns an array of objects combined using sliceRank and sliceCount. So now each array item now contains values of structure { date, count, rank }. Array.map is immutable so both slices will be the same.
You can try this.
let sliceRank=[{id: "Catan=rank", values : [{"date":"10/10/2020", "measurement":120} ]}];
let sliceCount=[{id: "Catan=count", values :[{"date":"10/10/2020", "measurement":20} ] }];
let newData=[];
const data = sliceRank.map((slice, sliceIndex) => {
return {
id:slice.id.split("=")[0],
values: slice.values.map(({ date, measurement }, valueIndex) => ({
date,
rank: measurement,
count: sliceCount[sliceIndex].values.map(r=> r.measurement)[0],
}))
}
})
console.log(data);
Related
Hello I have this code and It's working
for (let i in list) {
db.push({
name: list[i],
values: []
});
for (let j in data) {
db[i].values.push({
Date: data[j].Date,
count: parseInt(data[j][list[i]])
});
};
db[i].values.pop();
};
Im trying to convert it to this
list.forEach((el, i) => {
db.push({
name: list[i],
values: Array.prototype.call(data.forEach((d, j) => {
this.push({
Date: data[j].Date,
count: parseInt(data[j][list[i]])
});
}))
})
})
You could slice data to get only the items without the last and map the value.
let shortData = data.slice(0, -1),
db = list.map(name => ({
name,
values: shortData.map(({ Date, [name]: count }) => ({
Date,
count: +count
})
});
I've got an object of type : [ {name : 'xxx' , price: '555', quantity : '2' } , {...} ] and so one.
I got a class
getCartItems() {
let items = localStorage.getItem('item');
items = JSON.parse(items);
return items;
}
where i get this array.
Now i am getting index of the array, for example 0 , it should remove first array from object.
but when i do .remove, or other, it does not work. this.getCartItems()[index].remove or other does not work. Can you help me?
My guess is that you are mutating the object after you parse it and you never save it back.
You have to save the mutated object inside of your localStorage to make your removal of the first item persistant.
Look at the following example :
const localStorage = {
items: {
item: JSON.stringify([{
name: 'xxx',
price: '555',
quantity: '2',
}, {
name: 'yyy',
price: '666',
quantity: '5',
}, {
name: 'zzz',
price: '777',
quantity: '6',
}]),
},
getItem: str => localStorage.items[str],
setItem: (str, value) => {
localStorage.items[str] = value;
},
};
function getCartItems() {
const items = localStorage.getItem('item');
const parsedItems = JSON.parse(items);
// We remove the first element
const item = parsedItems.splice(0, 1);
// We save the value
localStorage.setItem('item', JSON.stringify(parsedItems));
return item;
}
console.log('First call ---');
console.log(getCartItems());
console.log('');
console.log('Second call ---');
console.log(getCartItems());
console.log('');
console.log('Third call ---');
console.log(getCartItems());
Use filter to get required items. In the following updated will not have earlier 0 index item. Now, the updated array you may want to set in localStorage again if required.
const items = getCartItems();
const indexToRemove = 0;
const updated = items.filter((,index) => index !== indexToRemove);
You can use array method filter to remove the object from array. This can look something like this:
getCartItems() {
let items = localStorage.getItem('item');
items = JSON.parse(items);
return items;
}
removeCart(){
return id; // the id that you will have from your a tag
}
const updatedItems = this.getCartItems().filter((item,index) => index !== this.removeCart()); // in updated items you will find your filtered out array of object
What is the best way to filter out data that exists within an object?
I was able to do use the below code when data was just an array of values but now I need to filter out any data where the item.QID exists in my array of objects.
Data Obj:
var data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob
}]
Snippet:
// I don't want to include data if this QID is in my object
this.employees = emp.filter(item =>!this.data.includes(item.QID));
From what I understand, includes only works on an array so I need to treat all of the QID values in my object as an array.
Desired Outcome: (assuming item.QID = ABC123)
this.employees = emp.filter(item =>!this.data.includes('ABC123'));
Result:
var data = [{
QID: 'DEF456',
Name: 'Bob'
}]
UPDATE:
Apologies, I left some things a little unclear trying to only include the necessary stuff.
// People Search
this.peopleSearchSub = this.typeahead
.distinctUntilChanged()
.debounceTime(200)
.switchMap(term => this._mapsService.loadEmployees(term))
.subscribe(emp => {
// Exclude all of the current owners
this.employees = emp.filter((item) => item.QID !== this.data.QID);
}, (err) => {
this.employees = [];
});
The above code is what I am working with. data is an object of users I want to exclude from my type-ahead results by filtering them out.
The question is a little ambiguous, but my understanding (correct me if I'm wrong), is that you want to remove all items from a list emp that have the same QID as any item in another list data?
If that's the case, try:
this.employees = emp.filter(item => !this.data.some(d => d.QID === item.QID))
some is an array method that returns true if it's callback is true for any of the arrays elements. So in this case, some(d => d.QID === item.QID) would be true if ANY of the elements of the list data have the same QID as item.
Try Object#hasOwnProperty()
this.employees = emp.filter(item =>item.hasOwnProperty('QID'));
You can use a for ... in to loop through and filter out what you want:
const data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob'
}]
let newData = [];
let filterValue = 'ABC123';
for (let value in data) {
if (data[value].QID !== filterValue) {
newData.push(data[value]);
}
}
newData will be your new filtered array in this case
You can use an es6 .filter for that. I also added a couple of elements showing the filtered list and an input to allow changing of the filtered value. This list will update on the click of the button.
const data = [{
QID: 'ABC123',
Name: 'Joe'
},
{
QID: 'DEF456',
Name: 'Bob'
}]
displayData(data);
function displayData(arr) {
let str = '';
document.getElementById('filterList').innerHTML = '';
arr.forEach((i) => { str += "<li>" + i.QID + ": " + i.Name + "</li>"})
document.getElementById('filterList').innerHTML = str;
}
function filterData() {
let filterValue = document.getElementById('filterInput').value;
filterText (filterValue);
}
function filterText (filterValue) {
let newArr = data.filter((n) => n.QID !== filterValue);
displayData(newArr)
}
<input id="filterInput" type="text" value="ABC123" />
<button type ="button" onclick="filterData()">Filter</button>
<hr/>
<ul id="filterList"><ul>
I am extracting data from a JSON feed and am trying to count the number of times each name (name_class) occurs.
I want to return an array of objects in the following format, where count refers to the number of times the name appears:
myArray = [{name:"John", count: 5}, {name: "Sarah", count: 2}, {name: "Oliver", count: 3}];
So far I have the following, but this does not count the number of occurrences, it simply adds another object to the array;
let namestUi = {
renderNames(names){
var counter2 = [];
let namesFound = names.map((name) => {
let {name_class} = name;
if(counter2.name == name_class){
counter2.count++;
} else { counter2.push({name: name_class, count: 1}); }
});
console.log(counter2);
return namesFound;
}
};
This is building the array of objects but not counting the number of occurrences.
function count(names){
// Count occurrences using a map (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
let map = new Map();
for (let name of names) {
map.set(name, (map.get(name) || 0) + 1);
}
// Transform to array of { name, count }
let result = [];
for (let [name, count] of map) {
result.push({name: name, count: count});
}
return result;
}
count(["a", "b", "c", "a", "b", "a"])
// [{"name":"a","count":3},{"name":"b","count":2},{"name":"c","count":1}]
There are some problems in how you use your counter variable. You access properties as if it is a plain object, but you defined it as an array. Also your map callback function is not returning any value.
You could use this code which uses a Map to key counters by name, and then applies Array.from to convert that Map to an array of objects as you requested:
let namestUi = {
renderNames(names){
return Array.from(
names.reduce( (counters, {name_class}) =>
counters.set(name_class, (counters.get(name_class) || 0) + 1),
new Map() ),
([name, count]) => ({name, count})
);
}
};
let result = namestUi.renderNames([
{ name_class: "John" },
{ name_class: "John" },
{ name_class: "Frank" },
{ name_class: "John" },
]);
console.log(result);
I have an array with keys like so:
['asdf12','39342aa','12399','129asg',...]
and a collection which has these keys in each object like so:
[{guid: '39342aa', name: 'John'},{guid: '129asg', name: 'Mary'}, ... ]
Is there a fast way to sort the collection based on the order of keys in the first array?
var sortedCollection = _.sortBy(collection, function(item){
return firstArray.indexOf(item.guid)
});
Here is just a simple add to the accepted answer in case you want to put the unmatched elements at the end of the sortedCollection and not at the beginning:
const last = collection.length;
var sortedCollection = _.sortBy(collection, function(item) {
return firstArray.indexOf(item.guid) !== -1? firstArray.indexOf(item.guid) : last;
});
Input:
var data1 = ['129asg', '39342aa'];
var data2 = [{
guid: '39342aa',
name: 'John'
}, {
guid: '129asg',
name: 'Mary'
}];
First create an index object, with _.reduce, like this
var indexObject = _.reduce(data2, function(result, currentObject) {
result[currentObject.guid] = currentObject;
return result;
}, {});
And then map the items of the first array with the objects from the indexObject, like this
console.log(_.map(data1, function(currentGUID) {
return indexObject[currentGUID]
}));
Output
[ { guid: '129asg', name: 'Mary' },
{ guid: '39342aa', name: 'John' } ]
Note: This method will be very efficient if you want to sort so many objects, because it will reduce the linear look-up in the second array which would make the entire logic run in O(M * N) time complexity.
This is the efficient & clean way:
(Import lodash identity and sortBy):
TS:
function sortByArray<T, U>({ source, by, sourceTransformer = identity }: { source: T[]; by: U[]; sourceTransformer?: (item: T) => U }) {
const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
const orderedResult = sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
return orderedResult;
}
Or in JS:
function sortByArray({ source, by, sourceTransformer = _.identity }) {
const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
const orderedResult = _.sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
return orderedResult;
}
You can use indexBy(), and at() to sort your collection. The advantage being that concise code and performance. Using sortBy() here does the trick, but your external array is already sorted:
var ids = [ 'cbdbac14', 'cf3526e2', '189af064' ];
var collection = [
{ guid: '189af064', name: 'John' },
{ guid: 'cf3526e2', name: 'Julie' },
{ guid: 'cbdbac14', name: 'James' }
];
_(collection)
.indexBy('guid')
.at(ids)
.pluck('name')
.value();
// → [ 'James', 'Julie', 'John' ]
Using at(), you can iterate over the sorted external collection, building a new collection from the source collection. The source collection has been transformed into an object using indexBy(). You do this so at() has key-based access for each of it's ids.