I'm decoding an object and so far I got it working. Let's say I have this object:
var person = [{
firstname: "Mike",
lastname: "123ñññ"
age: 20
}]
So in order to decode ñ and render ñ, I'm simply doing this:
new DOMParser().parseFromString(person[0].lastname, "text/html").documentElement.textContent;
and this will render the value
ñññ
which is what I want, so it will look like this:
lastname: "ñññ"
However, the issue that I'm facing is that I need to decode values for each property in the object because I may get those special characters for firstname or other properties. So my question is how to decode property values on an object assuming that the object may look like this:
var person = [{
name: "Mike",
lastname: "123ñññ"
age: 20,
employeer: {
name: 'ABC Company ñê',
supervisors:[
{
name: 'Steveä',
code: 'è468'
}
]
}
}]
NOTE:
I don't need help on decoding that values of each property on my object, since I'm already doing that, I just need to come up with a recursive function that will do that on a nested object
I think a recursive decode using DOMParser is a good idea. Here's an in-place transformer. Perform a deep copy first and then transform in-place if you prefer.
var person = [{
name: "Mike",
lastname: "123ñññ",
age: 20,
employer: {
name: 'ABC Company ñê',
supervisors: [
{
name: 'Steveä',
code: 'è468'
}
]
}
}];
console.log(person);
function htmlDecode(input)
{
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
function fix(obj) {
for (let prop in obj) {
switch (typeof obj[prop]) {
case 'object':
fix(obj[prop]);
break;
case 'string':
obj[prop] = htmlDecode(obj[prop]);
break;
}
}
}
fix(person);
console.log(person);
in functional languages there are libraries to recursively walk tree scructures. In clojure there is the zipper and walk for example.
you could write it yourself but it will quickly get complicated so I suspect using JSON.stringify + parse would give you what you need. Both functions take second argument that's replacer and reviver respectively that allow you to intercept the transformations and alter the values.
Here is example from the official documentation:
function replacer(key, value) {
// Filtering out properties
if (typeof value === 'string') {
return undefined;
}
return value;
}
var foo = {foundation: 'Mozilla', model: 'box', week: 45, transport: 'car', month: 7};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'
Try this:
function decodeObject(obj){
if(typeof obj == 'object'){
var text = JSON.stringify(obj),
div = document.createElement('div');
div.innerHTML = text;
obj = JSON.parse(div.childNodes[0].nodeValue);
}
return obj;
}
var person = decodeObject([{
name: "Mike",
lastname: "123ñññ",
age: 20
}]);
console.log(person);
Related
I have a object which has some properties for one user, and I have array of objects which is returned from API.
My goal is to check which object of Array of objects has the same property as the one single initial object, and then it should return only part of it's properities.
I have tried to use .map on Array of objects but it seems not workig.
Below is the code example. I have also prepared codesandbox if You wish.
const user =
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
car: "audi"
}
;
const usersAnimal = [
{
name: "jan",
lastName: "kowalski",
fullName: "jan kowalski",
animal: "cat",
animalSize: "small",
animalName: "Bat"
},
{
name: "john",
lastName: "smith",
fullName: "john smith",
animal: "dog",
animalSize: "middle",
animalName: "Jerry"
},
{
name: "Anna",
lastName: "Nilsson",
fullName: "Anna Nilsson",
animal: "cow",
animalSize: "big",
animalName: "Dorrie"
}
];
const filtered = usersAnimal.map((userAnimal)=>userAnimal.fullName === user.fullName && return userAnimal.animalName & userAnimal.animalSize & userAnimal.animal);
thanks
https://codesandbox.io/s/admiring-edison-qxff42?file=/src/App.js
For case like this, it would be far easier if you filter it out first then proceed using map:
const filtered = usersAnimal
.filter((animal) => animal.fullName === user.fullName)
.map(({ animalName, animalSize, animal }) => {
return {
animalName,
animalSize,
animal
};
});
I am providing a for loop solution as I haven't learnt many array methods in javascript.
For me the simplest option is to use a for loop and an if check to loop through the arrays values to check for included values.
for (let v in usersAnimal) {
if (usersAnimal[v].fullName === user.fullName) {
console.log(usersAnimal[v])
}
}
The code above will log the entire usersAnimal object containing the fullname we are looking for.
{
name: 'jan',
lastName: 'kowalski',
fullName: 'jan kowalski',
animal: 'cat',
animalSize: 'small',
animalName: 'Bat'
}
commented for further understanding
for (let v in usersAnimal) {
//loops though the array
if (usersAnimal[v].fullName === user.fullName) {
//when the index value 'v' has a fullname that matches the user fullname value
// it passes the if check and logs that object value
return console.log(usersAnimal[v])
//return true...
}
//return null
}
//etc
If you want to filter, I recommend you to use filter.
The map method will create a new array, the content of which is the set of results returned by each element of the original array after the callback function is operated
const user = {name:"jan",lastName:"kowalski",fullName:"jan kowalski",car:"audi"};
const usersAnimal = [{name:"jan",lastName:"kowalski",fullName:"jan kowalski",animal:"cat",animalSize:"small",animalName:"Bat"},{name:"john",lastName:"smith",fullName:"john smith",animal:"dog",animalSize:"middle",animalName:"Jerry"}];
// Get an array of matching objects
let filtered =
usersAnimal.filter(o => o.fullName === user.fullName);
// You get the filtered array, then you can get the required properties
filtered.forEach(o => {
console.log(
'animal:%s, animalSize:%s, animalName:%s',
o?.animal, o?.animalSize, o?.animalName
);
});
// Then use map to process each element
filtered = filtered.map(o => {
const {animal, animalSize, animalName} = o;
return {animal, animalSize, animalName};
});
console.log('filtered', filtered);
Is there an easy way to convert an object to name value pairs like jquery generates with .serializeArray()
This doesn't work:
var data = {
name: "John",
age: 26,
isMale: true,
occupation: null
}
var serialized = $(data).serailizeArray();
Is there an easy way to do this without looking at every property and converting them to name-value pairs?
I'm using a helper function that is written by someone else that adds a name value pair to each call before posting it to the server. Obviously it's not working if I give it a regular object or an array that has a regular object.
You can do this with a combination of Object.entries and map (assuming you want the data in the same format that serializeArray returns):
var data = {
name: "John",
age: 26,
isMale: true,
occupation: null
};
var result = Object.entries(data).map(([k, v]) => ({name: k, value: v}));
console.log(result);
This should do the trick if you're using ES6:
var data = {
name: "John",
age: 26,
isMale: true,
occupation: null
}
console.log(
Object.entries(data).map(([name, value]) => ({ name, value }))
)
// ES5:
console.log(
Object.keys(data).map(function (name) { return { name: name, value: data[name] } })
)
Is there a way to clone an object with only few properties of the object in JS?
For example..
var Person = {
name: "Bob",
age: 32,
salary: 20000
};
I have to create another person object with just the name and age property so that it will look something like this :
var clonedPerson = {
name: "Bob",
age: 32
};
I could do a deep clone of the object and delete. But I wanted to know if there are better ways to do it.
Using the latest ES6, you can achieve this by the following code..
const Person = {
name: "Bob",
age: 32,
salary: 20000
};
const { salary , ...clonedPerson } = Person
console.log(clonedPerson)
More simple?
var Person = {
name: "Bob",
age: 32,
salary: 20000
};
var ClonedPerson = jQuery.extend({}, Person);
delete ClonedPerson.salary;
console.log(JSON.stringify(Person));
console.log(JSON.stringify(ClonedPerson));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
an alternative approach using Array member methods:
var clone = Object.keys(Person) // convert to an Array of Person keys
.filter(function(key){return ["salary"].indexOf(key) == -1;}) // exclude key salary
.reduce(function(clone, current){clone[current] = Person[current]; return clone;}, {}); // convert back the array to a cloned literal object
So I have an array that contains objects with different attributes and I want to know how I can make multiple arrays with objects with the same attributes of the whole array.
I want to go from this
[
{name:”test”, place:”country”},
{name:”walkAndEat”, Long=100,Lat:15,Location:”place name”},
{name:”test2”,place:”Europe”}
]
To
[
{name:”test”, place:”country”},
{name:”test2”,place:”Europe”}
]
[
{name:”walkAndEat”, Long:100,Lat:15,Location:”place name”}
]
If you see objects being equal as having the same properties, you can keep the keys as (stringified) indices in a collection object and check if a properties-key already exists:
var arrcoll = {};
function add(o){
var keys = JSON.stringify(Object.keys(o).sort());
var arr = arrcoll[keys];
if(arr)
arr.push(o);
else
arrcoll[keys] = [o];
return arr;
}
This can be done on the fly or on a pre existing array as shown in this Fiddle
Suppose you have a list of objects that have different properties like so:
var placesOrPeople = [
{ name: 'Seymour Skinner', occupation: 'Principal' },
{ name: 'Kwik-E-Mart', lat: 23, long: 100 },
{ name: 'Sideshow Bob', occupation: 'Comic Foil' },
{ name: 'Flaming Tyre Yard', lat: 12, long: 88 },
{ name: 'Joe Quimby', occupation: 'Mayor' }
];
And you want them sorted into separate lists like so:
places = [
{ name: 'Kwik-E-Mart', lat: 23, long: 100 },
{ name: 'Flaming Tyre Yard', lat: 12, long: 88 }
];
people = [
{ name: 'Seymour Skinner', occupation: 'Principal' },
{ name: 'Sideshow Bob', occupation: 'Comic Foil' },
{ name: 'Joe Quimby', occupation: 'Mayor' }
];
You can use the built-in Array.filter command like so:
var places = placesOrPeople.filter(function(currentPlaceOrPerson) {
if (currentPlaceOrPerson.occupation !== undefined) {
// it must be a person, since locations don't have occupations
return true;
} else {
return false;
}
});
var people = placesOrPeople.filter(function(currentPlaceOrPerson) {
if (currentPlaceOrPerson.lat !== undefined && currentPlaceOrPerson.long !== undefined) {
// it must be a place, since people don't have co-ordinates
return true;
} else {
return false;
}
});
Javascript Objects are not set types, they are dynamic, meaning you can change them during execution.
JavaScript is a loosely typed or a dynamic language. That means you don't have to declare the type of a variable ahead of time. The type will get determined automatically while the program is being processed. That also means that you can have the same variable as different types:
var anything = arrayOfAnyOtherType[0];
is valid... If you loop your source array and populate it, you can define any behavior to each object
I have an object like this:
var person = {
name: "John",
surname: "Smith",
phone: "253 689 4555"
}
I want:
John,Smith,253 689 4555
Is there some easy way?
If possible, could you please provide an example where I can also define the separator?
You can use this one-liner in modern browsers
Object.keys(person).map(function(k){return person[k]}).join(",");
This code will be useful when you want to extract some property values from an array of objects as comma separated string.
var arrayObjects = [
{
property1: "A",
property2: "1"
},
{
property1: "B",
property2: "2"
},
{
property1: "C",
property2: "3"
}
];
Array.prototype.map.call(arrayObjects, function(item) { return item.property1; }).join(",");
Output - "A,B,C"
Here is a simpler one liner. It uses the Object.values() method instead of Object.keys
Object.values(obj).join(",");
try this:
var key,
person = {
name: "John",
surname: "Smith",
phone: "253 689 4555"
},
array = [];
for ( key in person ) {
if ( person.hasOwnProperty( key ) ) {
array.push( person[ key ] );
}
}
console.log( array.join( ',' ) );
or in function style:
var
getValues = function ( obj ) {
var key,
array = [];
for ( key in obj ) {
if ( obj .hasOwnProperty( key ) ) {
array.push( obj [ key ] );
}
}
return obj.join( ',' );
};
var person = {
name: "John",
surname: "Smith",
phone: "253 689 4555"
};
console.log( getValues( person ) );
Write a function like this:
function toCSV(obj, separator) {
var arr = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
arr.push(obj[key]);
}
}
return arr.join(separator || ",");
}
And then you can call it like:
toCSV(person, "|"); // returns "John|Smith|253 689 4555"
or
toCSV(person); // returns "John,Smith,253 689 4555"
var arr = [
{
key_1: "A",
key_2: "1"
},
{
key_1: "B",
key_2: "2"
},
{
key_1: "C",
key_2: "3"
}
];
var CSVOf_arr = arr.map((item) => { return item.key_1 }).join(',')
console.log('Comma seprated values of arr', CSVOf_arr)
OUTPUT: A,B,C
You might want to try this library - Underscore.js. It gives you really helpful methods and works across browsers.
Here you can do it like this -
_.values(person).join(",")
or
_.values(person).join("|")
The Object.values() method returns an array of a given object's own enumerable property values. It can be used to convert object properties to an array which can then be joined using .join(separator) to create the required string with separator defined in join function. But this will cause empty values to be joined as well. So for an object as
var person = {
name: "John",
surname: "Smith",
phone: ""
}
output for
Object.values(person).join(',')
will be
John,Smith,
with an additional "," at the end. To avoid this .filter() can be used to remove empty elements from array and then use join on filtered array.
Object.values(person).filter(Boolean).join(',')
will output
John,Smith
Object.values(person).join('/')
Another way is to use lodash function _.toString()
console.log( _.toString( Object.values( person ) ) );
==> John,Smith,253 689 4555
Check the link below
https://lodash.com/docs/4.17.5#toString
var person = {
name: "John",
surname: "Smith",
phone: "253 689 4555"
}
let personData = ${person.name},${person.surname},${person.phone}
With this `` mark and $ dollar sign you will get the result.
Just use object.values() and use toString() method
Object.values(person).toString()