Related
Not sure how to parse through a list of strings within a loop regarding this dictionary.
var student_nicknames = [
{name: "William", nickname: "Bill"},
{name: "Joseph", nickname: "Joe"},
{name: "Maria", nickname: "Mary"},
{name: "Richard", nickname: ["Rick", "Ricky"]},
{name: "Elizabeth", nickname: ["Liz", "Lisa", "Beth"]}
];
total_nicknames = function(){
student_nicknames.forEach(function(student) {
console.log(student.nickname);
});
}
Output
Bill
Joe
Mary
[ 'Rick', 'Ricky' ]
[ 'Liz', 'Lisa', 'Beth' ]
Desired Output
Bill
Joe
Mary
Rick
Ricky
Liz
Lisa
Beth
All you need to do is to have an if condition to check if nickname property of each student is an array or not, if it is an array, then you can loop through it and print each item individually, otherwise follow your logic.
var student_nicknames = [
{ name: "William", nickname: "Bill" },
{ name: "Joseph", nickname: "Joe" },
{ name: "Maria", nickname: "Mary" },
{ name: "Richard", nickname: ["Rick", "Ricky"] },
{ name: "Elizabeth", nickname: ["Liz", "Lisa", "Beth"] }
];
const total_nicknames = function () {
student_nicknames.forEach(function (student) {
if (Array.isArray(student.nickname)) { // <- HERE
student.nickname.forEach((e) => console.log(e));
} else {
console.log(student.nickname);
}
});
};
total_nicknames();
you can check whether the type is an Array or not:
total_nicknames = function(){
student_nicknames.forEach(function(student) {
if (Array.isArray(student.nickname)) {
student.nickname.forEach(function (nickname) {
console.log(nickname)
})
} else {
console.log(student.nickname);
}
});
}
Use map() to get only nicknames and then use flat() to flatten the array.
var student = [
{name: "William", nickname: "Bill"},
{name: "Joseph", nickname: "Joe"},
{name: "Maria", nickname: "Mary"},
{name: "Richard", nickname: ["Rick", "Ricky"]},
{name: "Elizabeth", nickname: ["Liz", "Lisa", "Beth"]}
];
console.log(student.map(({nickname})=>nickname).flat())
a simple solution based on recursion.
function total_nicknames(student_nicknames) {
for(let i = 0; i < student_nicknames.length; i++){
let student = student_nicknames[i];
if(typeof student === 'object' && student !== null) {
if(Array.isArray(student.nickname)){
total_nicknames(student.nickname);
}else {
console.log(student.nickname);
}
}else {
console.log(student);
}
}
}
console.log(total_nicknames(student_nicknames));
/* output */
// "Bill"
// "Joe"
// "Mary"
// "Rick"
// "Ricky"
// "Liz"
// "Lisa"
// "Beth"
You can build a small recursive loop, by calling the total_nicknames function again, if student.nickname is an array. You also need to use || (OR) operator, to get the nickname (which would be a string, if it loops over the array) and not undefined (since string object doesn't have any nickname method/property).
var student_nicknames = [{
name: "William",
nickname: "Bill"
},
{
name: "Joseph",
nickname: "Joe"
},
{
name: "Maria",
nickname: "Mary"
},
{
name: "Richard",
nickname: ["Rick", "Ricky"]
},
{
name: "Elizabeth",
nickname: ["Liz", "Lisa", "Beth"]
}
];
total_nicknames = function(arr) {
arr.forEach(function(student) {
if (Array.isArray(student.nickname)) {
total_nicknames(student.nickname)
} else
console.log((student.nickname || student));
});
}
total_nicknames(student_nicknames);
I have no idea how I can sort an array of objects comparing two keys. I have array:
const arr = [
{
age: "20",
group: "XXX",
id: "3L1aa1558002753379",
menu: "standard",
name: "Adam"
},
{
age: "22",
group: "XXX",
id: "xhNt11558002753379",
menu: "standard",
name: "Ola"
},
{
otherid: "3L1aa1558002753379",
age: "25",
group: "YYY",
id: "6ryVK1558002753379",
menu: "standard",
name: "Wommman"
},
{
otherid: "xhNt11558002753379",
age: "25",
group: "YYY",
id: "aL1aa1558002753312",
menu: "standard",
name: "xxxxxy"
},
{
age: "25",
group: "YYY",
id: "6ryVK1558002753379",
menu: "standard",
name: "xxxxxo"
}
,
{
otherid: "1ryVK1558002753372",
age: "25",
group: "YYY",
id: "9ryVK155a002753370",
menu: "standard",
name: "xxxxxo"
},
{
age: "25",
group: "YYY",
id: "1ryVK1558002753372",
menu: "standard",
name: "xxxxxo"
}
];
I want to sort in this way: if "id" and "otherid" is the same - let objects be next to each other. I do not know how to do it, would anyone be so good?
Like here:
const arr = [
{
age: "20",
group: "XXX",
id: "3L1aa1558002753379",
menu: "standard",
name: "Adam"
},
{
otherid: "3L1aa1558002753379",
age: "25",
group: "YYY",
id: "6ryVK1558002753379",
menu: "standard",
name: "Wommman"
},
{
age: "22",
group: "XXX",
id: "xhNt11558002753379",
menu: "standard",
name: "Ola"
},
{
otherid: "xhNt11558002753379",
age: "25",
group: "YYY",
id: "aL1aa1558002753312",
menu: "standard",
name: "xxxxxy"
},
{
age: "25",
group: "YYY",
id: "1ryVK1558002753372",
menu: "standard",
name: "xxxxxo"
},
{
otherid: "1ryVK1558002753372",
age: "25",
group: "YYY",
id: "9ryVK155a002753370",
menu: "standard",
name: "xxxxxo"
},
{
age: "25",
group: "YYY",
id: "6ryVK1558002753379",
menu: "standard",
name: "xxxxxo"
}
,
];
I tried something similar to this: Javascript sort array by two fields but it failed
You pointed out, that you only need to compute pairs and render them in a react application.
It would make much more sense to structure your data in a way your view can directly render it.
Since you are in control of the data, you don't need to generate a flat list. You can setup the pairs (of students, or whatever) using a hierarchical structure, or nested obejcts.
let students = [{name: 'Jon', id:0}, {name: 'Peter', id: 1}, {name: 'Steve', id:2}, {name: 'Joe', id: 3}]
let pairs = [{a: students [3], b: students[1]}, {a: students [2], b: students [0]}];
console.log (pairs);
Now if you want to render those pairs, you already have the data in the structure you need.
render () {
return pairs.map (pair => <Pair data={pair} />)
}
You can also flatten the pairs array and render a flat list of elements next to each other if you prefer.
let students = [{name: 'Jon', id:0}, {name: 'Peter', id: 1}, {name: 'Steve', id:2}, {name: 'Joe', id: 3}]
let pairs = [{a: students [3], b: students[1]}, {a: students [0], b: students [2]}];
const flatten = (flat, {a, b}) => [...flat, a, b];
const sorted = pairs.reduce (flatten, []);
console.log (sorted)
const Student = data => <div>{data.name}</div>
const Pair = pair => <div>
<Student data={pair.a} />
<Student data={pair.b} />
</div>
const renderFlat = () => {
return sorted.map (student => <Student data={student} />
}
const renderPairs = () => {
reutnr pairs.map (pair => <Pair data={pair} />)
}
I hope I make at least a bit sense. - Here is the sort function in any case
function sort (arr) {
let otherids = arr.reduce ((lkp, obj) => {
if (obj.otherid)
lkp [obj.otherid] = obj;
return lkp;
}, {});
let sorted = [];
for (var i=0; i < arr.length; i++) {
let obj = arr [i];
if (!!~sorted.indexOf (obj)) continue;
if (otherids [obj.id]) {
sorted.push (obj)
sorted.push(otherids[obj.id])
}
}
return sorted.concat (arr.filter (obj => !~sorted.indexOf (obj)));
}
let sorted = sort (arr);
console.log (sorted);
<script>var arr=[{age:"20",group:"XXX",id:"3L1aa1558002753379",menu:"standard",name:"Adam"},{age:"22",group:"XXX",id:"xhNt11558002753379",menu:"standard",name:"Ola"},{otherid:"3L1aa1558002753379",age:"25",group:"YYY",id:"6ryVK1558002753379",menu:"standard",name:"Wommman"},{otherid:"xhNt11558002753379",age:"25",group:"YYY",id:"aL1aa1558002753312",menu:"standard",name:"xxxxxy"},{age:"25",group:"YYY",id:"6ryVK1558002753379",menu:"standard",name:"xxxxxo"},{otherid:"1ryVK1558002753372",age:"25",group:"YYY",id:"9ryVK155a002753370",
menu:"standard",name:"xxxxxo"},{age:"25",group:"YYY",id:"1ryVK1558002753372",menu:"standard",name:"xxxxxo"}];</script>
The key to sorting strings is to use String.localeCompare(). Numbers, dates and booleans are much simpler.
Here is an example of sorting a list of Objects by two string columns - name and menu:
arr.sort(function comparerFn(L, R){
if(L.name !== R.name)
return (new String(L.name)).localeCompare(R.name)===1?1:-1
if(L.menu !== R.menu)
return (new String(L.menu)).localeCompare(R.menu)===1?1:-1
return 0
})
Reasoning for odd ===1?1:-1 syntax: localeCompare() returns 1 or 0 but sort compareFn requires either 0: (leave sorting as-is), >0: (L is before R), <0: (R is before L)
I want to edit JavaScript object.
I have an JavaScript object like this
data_without_id = [
0: {id: 1, name: "Mary", age: null}
1: {id: 2, name: "Bob", age: 33}
2: {id: 1, name: "Kelly", age: 40}
]
I want to convert this object into this
data_without_id = [
0: {id: 1, name: "Kelly", age: 40}
1: {id: 2, name: "Bob", age: 33}
]
What I need to do is:
Group by id
Get latest value.
I tried using Array.prototype.reduce(), but I can't get the result I need...
Using the function reduce would be as follow:
The function reduce for grouping and the function Object.values for extracting the values.
let data_without_id = [ { id: 1, name: "Mary", age: null }, { id: 2, name: "Bob", age: 33 }, { id: 1, name: "Kelly", age: 40 }],
result = Object.values(data_without_id.reduce((a, {id, name, age}) => {
a[id] = {id, name, age};
return a;
}, Object.create(null)));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use .reduce by making the accumulator an object that has keys of the id. This way you can overwrite any previously seen objects which had the same id, and then use Object.values to get your array of objects:
const data_without_id = [{id: 1, name: "Mary", age: null}, {id: 2, name: "Bob", age: 33}, {id: 1, name: "Kelly", age: 40}],
res = Object.values(data_without_id.reduce((acc, obj) =>
(acc[obj.id] = obj, acc)
, {}));
console.log(res);
You could just simply use a for/of loop to create a copy of the data where the last object with a particular id will always be the object returned in the output data. This avoids the "grouping" part of the code but still returns the correct data.
const data_without_id = [
{ id: 1, name: "Mary", age: null },
{ id: 2, name: "Bob", age: 33 },
{ id: 1, name: "Kelly", age: 40 }
];
function lastId(arr) {
const out = [];
for (let obj of arr) {
// If you don't create a copy of each object the returned
// data will simply be contain _references_ to the original
// data. Changes in the original data will be reflected
// in the returned data
out[obj.id - 1] = { ...obj };
}
return out;
}
const lastIds = lastId(data_without_id);
console.log(lastIds);
I'm sure this question has been asked in some form here before, but I am having trouble finding the right solution. I have an array of objects like this:
[
{id:"124", name:"Joe", lname:"Smith", age:"14"},
{id:"124", name:"Joe", lname:"Smith", age:"17"},
{id:"124", name:"Joe", lname:"Smith", age:"21"},
{id:"128", name:"Tom", lname:"Cans", age:"18"},
{id:"132", name:"Mik", lname:"Brak", age:"21"}
];
and I would like to shorten this array so that it only includes objects with unique id keys, as well as only the keys id, name, lname. The output I'm going for then is:
[
{id:"124", name:"Joe", lname:"Smith"},
{id:"128", name:"Tom", lname:"Cans"},
{id:"132", name:"Mik", lname:"Brak"}
];
What I've done so far - I can use the following code snippet to create an array of unique IDs, but that isn't getting me to where I need to go:
let uniqueIDs = [... new Set(mydata.map(val => val.id))];
Any help is appreciated!!
Store your array items in an object, indexed by id, and skip any which you already have:
var obj = {}
[ {id:"124", name:"Joe", lname:"Smith", age:"14"},
{id:"124", name:"Joe", lname:"Smith", age:"17"},
{id:"124", name:"Joe", lname:"Smith", age:"21"},
{id:"128", name:"Tom", lname:"Cans", age:"18"},
{id:"132", name:"Mik", lname:"Brak", age:"21"}
].forEach(function(d){
if ( ! obj[d.id] ) {
// omit the info you're not interested in
obj[d.id] = { id: d.id, name: d.name, lname: d.lname }
}
})
var uniq = Object.values(obj);
console.log(uniq)
You could take a Set of JSON strings and map them by parsing it.
var array = [{ id: "124", name: "Joe", lname: "Smith", age: "14" }, { id: "124", name: "Joe", lname: "Smith", age: "17" }, { id: "124", name: "Joe", lname: "Smith", age: "21" }, { id: "128", name: "Tom", lname: "Cans", age: "18" }, { id: "132", name: "Mik", lname: "Brak", age: "21" }],
unique = Array.from(
new Set(array.map(({ id, name, lname }) => JSON.stringify({ id, name, lname }))),
JSON.parse
);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
First step is to create a data structure where you can be sure your entries are unique. I like reduce to convert an array to a map.
const arrayToMap = array.reduce((obj, { id, name, lname}) => ({ ...obj, [id]: { id, name, lname }), {});
Then you need to build the map to an array by iterating over the keys.
const mapToArray = Object.keys(arrayToMap).map(key => ({ ...arrayToMap[key] });
Here's an approach using Set and filter to remove duplicate id keys and map to remove the age key:
const data = [
{id: "124", name: "Joe", lname: "Smith", age: "14"},
{id: "124", name: "Joe", lname: "Smith", age: "17"},
{id: "124", name: "Joe", lname: "Smith", age: "21"},
{id: "128", name: "Tom", lname: "Cans", age: "18"},
{id: "132", name: "Mik", lname: "Brak", age: "21"},
];
const ids = new Set(data.map(e => e.id));
const result = data
.filter(e => ids.delete(e.id))
.map(({id, name, lname}) => ({id, name, lname}))
;
console.log(result);
We have an array of objects like:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
And an array of a attribute values of the objects in object
const names = ["lisa", "bob"]
How can we find persons with name in the names array using es6, like:
const filteredPersons = [{
name: "lisa",
age: 43
}, {
name: "bob",
age: 67
}];
ES6
Use filter function with predicate and in it check the existence of the name in the names array.
const persons = [
{name: "john", age:23},
{name: "lisa", age:43},
{name: "jim", age:101},
{name: "bob", age:67}
];
const names = ["lisa", "bob"];
const filtered = persons.filter(person => names.includes(person.name));
console.log(filtered);
You can use filter() and inlcudes() to get required result.
DEMO
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({
name
}) => names.includes(name)))
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would suggest to use indexOf as includes does not work in IE browser. Also, using {name} works as Destructuring assignment that will hold the value of name property of the object.
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({name}) => names.indexOf(name) !== -1))
lodash
You can try following
const persons = [{name: "john", age: 23},
{name: "lisa",age: 43},
{name: "jim", age: 101},
{name: "bob",age: 67}];
const names = ["lisa", "bob"]
const filteredPersons = _.filter(persons, function(person) {
return _.indexOf(names, person.name) !== -1;
});
console.log(filteredPersons);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
In case you want to perform it in n complexity, here is a way to do it:
Create a map with key as person's name and value as person's object.
Map the criteria array and extract the person objects from the map create in step 1.
Here is a working demo:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
const map = persons.reduce((acc, item) => {
acc[item.name] = item;
return acc;
}, {});
const result = names.map(name => map[name]);
console.log(result);
Note: This solution assumes that only unique person names are in the source array. It needs to be tweaked to handle duplicates.
See Closures, Set, and Array.prototype.filter() for more info.
// Input.
const persons = [{name: "john",age: 23}, {name: "lisa",age: 43}, {name: "jim",age: 101}, {name: "bob",age: 67}]
const names = ["lisa", "bob"]
// Filter.
const filter = (A, B) => (s => A.filter(x => s.has(x.name)))(new Set(B))
// Output.
const output = filter(persons, names)
// Proof.
console.log(output)