Convert object to array of strings? - javascript

I am writing in my save method but here am getting as a list of array. but wanted to convert to set of string.
mySys: $scope.stringArrayToObjectArray($scope.editmySystems,"name");
$scope.editmySystems holds value-
0 :f
id: svg
name:"JASSI"
1 :f
id: svg2
name:"JASSYY"
length: 2
So for conversion i wrote one function-
$scope.stringArrayToObjectArray = function(stringArray, fieldName) {
var objectArr = [];
angular.forEach(stringArray, function(singleString) {
objectArr[fieldName]=singleString.name;
});
return objectArr;
};
currently objectArr is returning as-
name: "JASON2"
Expected o/p- objectArr should return-
name: ["JASSI","JASSYY"]
Please suggest

Basically you could just use:
var stringArray = [{id: 'svg', name: 'JASSI'}];
var objectArr = [];
stringArray.map(function(item) {
objectArr.push(item.name);
});
console.log(objectArr);

It's close but you're setting indexes on an array which will be an object. Instead, simply append the field name.
$scope.stringArrayToObjectArray = function(stringArray, fieldName) {
var objectArr = [];
angular.forEach(stringArray, function(singleString) {
objectArr.push(singleString[fieldName]);
});
return objectArr;
};

You could use Array#map and a callback which returns the wanted value of the key of the object.
The map() method creates a new array with the results of calling a provided function on every element in this array.
function getValues(array, key) {
return array.map(function (a) {
return a[key];
});
}
var data = [{ id: 'svg', name: 'JASSI' }, { id: 'svg2', name: 'JASSYY' }];
console.log(getValues(data, 'name'));

Related

Modify JavaScript code to use higher order functions

My below code is working fine and gives the correct desired output. But I am trying to use map, filter etc. instead of for loop. Lodash map and filter also works.
var arr = [
{"comp_id":1, desc: 'from comp1', updated: true},
{
"comp_id":2, desc: 'from comp2', updated: false}
];
var complaint_sources = [
{"comp_id":2,"consumer_source":"Hotline In","description_option":"English"},
{"comp_id":1,"consumer_source":"Online","description_option":"Other"},
{"comp_id":1,"consumer_source":"Email","description_option":null},
{"comp_id":2,"consumer_source":"Email","description_option":null}]
for(let i =0 ;i<arr.length;i++) {
let x=[];
for(let j=0;j<complaint_sources.length;j++){
if(arr[i].comp_id === complaint_sources[j].comp_id){
x.push(complaint_sources[j]);
arr[i].comp_src = x;
}
}
}
console.log(arr);
Basically I am looping through arr array and inside that looping through the complaint_sources array and when the comp_id matches I am modifying the arr array and adding a comp_src property to the object of arr array. This comp_src property will be an array of complaint_sources matched by comp_id.
this will work:
var arr = [
{"comp_id":1, desc: 'from comp1', updated: true},
{"comp_id":2, desc: 'from comp2', updated: false}
];
var complaint_sources = [
{"comp_id":2,"consumer_source":"Hotline In","description_option":"English"},
{"comp_id":1,"consumer_source":"Online","description_option":"Other"},
{"comp_id":1,"consumer_source":"Email","description_option":null},
{"comp_id":2,"consumer_source":"Email","description_option":null}
];
const grouped_sources = complaint_sources.reduce((acc, value) => {
(acc[value.comp_id] = acc[value.comp_id] || []).push(value);
return acc;
}, {})
const data = arr.map((comp) => ({
...comp,
comp_src: grouped_sources[comp.comp_id]
}));
console.log(data);

Javascript using filter/includes on an array of objects

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>

What is the best way to convert an array of strings into an array of objects?

Let's say I have an array of emails:
['a#gmail.com', 'b#gmail.com', 'c#gmail.com']
I need to convert it into an array of objects that looks like this:
[
{
id: 'a#gmail.com',
invite_type: 'EMAIL'
},
{
id: 'b#gmail.com',
invite_type: 'EMAIL'
},
{
id: 'c#gmail.com',
invite_type: 'EMAIL'
}
]
In order to do that, I have written the following code:
$scope.invites = [];
$.each($scope.members, function (index, value) {
let inviteMember = {
'id': value,
invite_type: 'EMAIL'
}
$scope.invites.push(inviteMember);
});
Is there any better way of doing this?
Since you're already using jQuery, you can use jQuery.map() like this:
var originalArray = ['a#gmail.com', 'b#gmail.com', 'c#gmail.com']
var newArray = jQuery.map(originalArray, function(email) {
return {
id: email,
invite_type:'EMAIL'
};
});
jQuery.map() translates all items in a given array into a new array of items. The function I am passing to jQuery.map() is called for every element of the original array and returns a new element that is written to the final array.
There is also the native Array.prototype.map() which is not supported in IE8. If you're not targeting IE8 or if you use a polyfill, then you can use the native .map():
var newArray = originalArray.map(function(email) {
return {
id: email,
invite_type:'EMAIL'
};
});
This pattern
targetArray = []
sourceArray.forEach(function(item) {
let x = do something with item
targetArray.push(x)
})
can be expressed more concisely with map:
targetArray = sourceArray.map(function(item) {
let x = do something with item
return x
})
in your case:
$scope.invites = $scope.members.map(function(value) {
return {
id: value,
invite_type: 'EMAIL'
}
});

Lodash sort collection based on external array

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.

How to push an object in an Array?

Iam trying to push in array an object, but I get always error.
fCElements = [],
obj = {};
obj.fun = myFunction;
obj.id = 2;
fCElements.push ({
obj,
myid:2,
name:'klaus'
})
how I can push into array functions like "myFunction"?
Thanks
In the Object literal, you can only give key-value pairs. Your obj doesn't have any value.
Instead, you can do like this
var fCElements = [];
fCElements.push({
obj: {
fun: myFunction,
id: 2
},
myid: 2,
name: 'klaus'
});
Now, you are creating a new object, obj, on the fly, while pushing to the array. Now, your fCElements look like this
[ { obj: { fun: [Function], id: 2 }, myid: 2, name: 'klaus' } ]
You need to give your obj property a name (or a value).
var obj = {};
obj.fun = myFunction;
obj.id = 2;
fCElements.push ({
obj:obj,
myid:2,
name:'klaus'
});
The object you are pushing to the array seems off. It will try to push this object:
{
{fun: myfunction, id: 2},
myid: 2,
name: 'klaus'
}
Which is an invalid object since the first value has no key. You should do it like this instead:
fCElements.push ({
myObj:obj,
myid:2,
name:'klaus'
});

Categories