Max element in an array in dailogflow - javascript

I am trying to calculate max element in an array . I tried this code but it is returning [object Object]
Is there something i am missing while doing in dailogflow.
function studentgroup(agent){
let games = [
{ id: 1, name: 'Star Wars: Imperial Assault', votes: 3},
{ id: 2, name: 'Game of Thrones: Second Edition', votes: 4 },
{ id: 3, name: 'Merchans and Marauders', votes: 5 },
{ id: 4, name: 'Eclipse', votes: 6 },
{ id: 5, name: 'Fure of Dracula', votes: 2 }
];
let maxGame = games.reduce((max, game) => max.votes > game.votes ? max : game);
agent.add(`${maxGame}`);
}

You can simply find the maximum element by iterating over the array.
let games = [
{ id: 1, name: 'Star Wars: Imperial Assault', votes: 3},
{ id: 2, name: 'Game of Thrones: Second Edition', votes: 4 },
{ id: 3, name: 'Merchans and Marauders', votes: 5 },
{ id: 4, name: 'Eclipse', votes: 6 },
{ id: 5, name: 'Fure of Dracula', votes: 2 }
];
maxElement = -Infinity;
element = null
for (const game of games) {
if (game.votes > maxElement) {
maxElement = game.votes;
element = game;
}
}
console.log(element)

The issue is that maxGame is an object. Using your example, that object will be
{ id: 4, name: 'Eclipse', votes: 6 }
But agent.add() is expecting to send back a string. The default "string" form of an object is "[object Object]", as you've seen.
You probably want to return something that makes more sense when displayed or read aloud, so it might make more sense for that line to be something like
agent.add(`The winner, with ${maxElement.votes} votes, is ${maxElement.name}.`)
which, given the example, would say something like
The winner, with 6 votes, is Eclipse.

Related

insert an array that has the same level

newbie here. I have a set of arrays. My target is to join 1 data to another data if they have the same values. For example, player 1 = level 1, and player 6 = level 1, therefore they'll be joined on the same array and inserted to the database. As far as I know, I think it has to do with for-each. How can I make it work? Thank you in advance.
const players = [
{
id: 1,
name: 'player1',
level: '1',
},
{
id: 2,
name: 'player2',
level: '2',
},
{
id: 3,
name: 'player3',
level: '3',
},
{
id: 4,
name: 'player4',
level: '3',
},
{
id: 5,
name: 'player5',
level: '2',
},
{
id: 6,
name: 'player6',
level: '1',
}
];
You could make a helper function to filter your array for specific levels:
const filterByLevel = (players, level) => players.filter(player => player.level === level);
// create new array only containing players with the given level
const levelTwoPlayers = filterByLevel(players, '2');
console.log(JSON.stringify(levelTwoPlayers));
// output: [{"id":2,"name":"player2","level":"2"},{"id":5,"name":"player5","level":"2"}]
Hope this helps - have fun coding

Javascript re-order array of object by value

How do I re-order array of object showing below by follow value. If follow value is not -1, move the item below to the item that has the id value same as follow value.
Here is the example.
let charObj = [
{ id: 8, name: 'Catelyn Stark', follow: -1 },
{ id: 7, name: 'Jaime Lannister', follow: 8 },
{ id: 3, name: 'Jon Snow', follow: -1 },
{ id: 4, name: 'Daenerys Targaryen', follow: 7 },
{ id: 5, name: 'Sansa Stark', follow: 4 }
];
Expected output will be;
let charObj = [
{ id: 8, name: 'Catelyn Stark', follow: -1 },
{ id: 7, name: 'Jaime Lannister', follow: 8 },
{ id: 4, name: 'Daenerys Targaryen', follow: 7 },
{ id: 5, name: 'Sansa Stark', follow: 4 },
{ id: 3, name: 'Jon Snow', follow: -1 }
];
Not sure if I can use sort(). What is the best way to re-order this object?
I think this will do what you're asking. I'm sure it could be made more efficient, but unless your list gets quite large that shouldn't make much practical difference. Also, this assumes any character will only have one follower. If that's not the rule, then the function will have to be adjusted.
let charObj = [
{ id: 8, name: "Catelyn Stark", follow: -1 },
{ id: 7, name: "Jaime Lannister", follow: 8 },
{ id: 3, name: "Jon Snow", follow: -1 },
{ id: 4, name: "Daenerys Targaryen", follow: 7 },
{ id: 5, name: "Sansa Stark", follow: 4 }
];
function sortChars(chars) {
let result = [];
let leaders = chars.filter(c => c.follow === -1);
for (let i = 0; i < leaders.length; i++) {
let current = leaders[i];
while (current) {
result.push(current);
let next = charObj.find(c => c.follow === current.id);
current = next;
}
}
return result;
}
console.log(sortChars(charObj));

How to find most perfect matching of some part of a string with an object's string value from a list of objects in javascript?

I have a list in frontend storedList. I need to check if some part of string str1 perfectly matches with any value of text parameter in storedList.
I have tried using includes() and got output given below.
let storedList = [
{ id: 1, text: 'Higher Education' },
{ id: 2, text: 'Higher Education in Physics' },
{ id: 3, text: 'Higher Education in Chemistry' },
{ id: 4, text: 'Higher Education in Math' },
{ id: 5, text: 'Higher Education in Biology' },
{ id: 6, text: 'Higher Education in History' },
{ id: 7, text: 'Higher Education in Economics' },
];
let str1 = 'unnecessay texts Higher Education in Biology unnecessary texts';
for (let row of storedList) {
console.log(str1.includes(row.text));
// output
// true
// false
// false
// false
// true
// false
// false
}
Now I have two problems.
As we can see there are two true results for "Higher Education" and "Higher Education in Biology". But I only want the last one as it is more accurate than the first one. How to do that?
My storedList might have upto 60,000 objects in the list. So for checking the string str1 I need to loop for 60,000 times with my process! And what if I have to check the storedList for 1000 different strings. It's 60,000 * 1000 times!
Really need a better and efficient solution.
You can use Array.reduce() and take the object with the longer text, which is also included in str1:
const storedList = [
{ id: 1, text: 'Higher Education' },
{ id: 2, text: 'Higher Education in Physics' },
{ id: 3, text: 'Higher Education in Chemistry' },
{ id: 4, text: 'Higher Education in Math' },
{ id: 5, text: 'Higher Education in Biology' },
{ id: 6, text: 'Higher Education in History' },
{ id: 7, text: 'Higher Education in Economics' },
];
const str1 = 'unnecessay texts Higher Education in Biology unnecessary texts';
const result = storedList.reduce((r, o) =>
o.text.length > r.text.length && str1.includes(o.text) ? o : r
);
console.log(result);

How can I optimally group a list of objects by their sub object?

I'm trying to group some JavasScript objects by their shared similar object. I can do this effortlessly in Ruby, but for the life of my I (somewhat embarrassingly) can't figure this out in JS in linear time. JS doesn't seem to allow object literals as keys, at least for the purposes of reducing.
I have data shaped like this, as a result from a GraphQL query:
[
{
id: 1,
name: 'Bob',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 3,
name: 'Sheila',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 2,
name: 'Tom',
room: {
id: 3,
name: 'Bathroom'
}
}
]
In the UI, we're going to display the objects by the room they're in. We need to keep a reference to the room itself, otherwise we'd just sort by a room property.
What I'm trying to do is reshape the data into something like this:
{
{id: 5, name: 'Kitchen'}: [{id: 1, name: 'Bob'}, {id: 3, name: 'Sheila'}],
{id: 3, name: 'Bathroom'}: [{id: 2, name: 'Tom'}]
}
As you can see, the people are grouped together by the room they're in.
It could also be shaped like this...
[
{ room: {id: 5, name: 'Kitchen'}, people: [{id: 1, name: 'Bob', ...}] },
{ room: {id: 3, name: 'Bathroom', people: [{id: 2, name: 'Tom'}]
]
However it comes out, we just need the people grouped by the rooms in linear time.
I've tried lodash's groupBy, using both map and reduce, just doing for loops that put the list together, etc. I'm stumped because without being able to use an object literal (the room) as a hash index, I don't know how to efficiently group the outer objects by the inner objects.
Any help is greatly appreciated.
Update: adding clarity about trying to do it with linear time complexity - the most efficient equivalent of this Ruby code:
h = Hash.new { |h, k| h[k] = [] }
value.each_with_object(h) { |v, m| m[v[:room]] << v }
You can solve this using lodash#groupBy and lodash#map to gather and transform each group. Additionally, we use lodash#omit to remove the room object from each person from the people array.
var result = _(data)
.groupBy('room.id')
.map(people => ({
room: { ...people[0].room },
people: _.map(people, person => _.omit(person, 'room'))
})).value();
var data = [
{
id: 1,
name: 'Bob',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 3,
name: 'Sheila',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 2,
name: 'Tom',
room: {
id: 3,
name: 'Bathroom'
}
}
];
var result = _(data)
.groupBy('room.id')
.map(people => ({
// make sure to create a new room object reference
// to avoid mutability
room: { ...people[0].room },
people: _.map(people, person => _.omit(person, 'room'))
})).value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
You can use reduce to create an object of people indexed by rooms and then get that object's values, no library needed:
const input=[{id:1,name:'Bob',room:{id:5,name:'Kitchen'}},{id:3,name:'Sheila',room:{id:5,name:'Kitchen'}},{id:2,name:'Tom',room:{id:3,name:'Bathroom'}}]
const output = Object.values(
input.reduce((a, { id, name, room }) => {
const roomName = room.name;
if (!a[roomName]) a[roomName] = { room, people: [] };
a[roomName].people.push({ id, name });
return a;
}, {})
);
console.log(output);
Objects like
{id: 5, name: 'Kitchen'}: [{id: 1, name: 'Bob'}, {id: 3, name: 'Sheila'}],
in your question can't be properties like that unless the structure is a Map. Ordinary Javascript objects can only have string (/ number) properties.
One alternative is to use reduce in order to groupBy the rooms.
const input = [{
id: 1,
name: 'Bob',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 3,
name: 'Sheila',
room: {
id: 5,
name: 'Kitchen'
}
},
{
id: 2,
name: 'Tom',
room: {
id: 3,
name: 'Bathroom'
}
}
];
const res = input
.map(person => ({
person: {
id: person.id,
name: person.name
},
room: person.room
}))
.reduce((rooms, person) => {
const room = rooms.find(room => room.id === person.room.id) ||
{ room: person.room };
const idx = rooms.indexOf(room);
room.people = room.people ?
[...room.people, person.person] :
[person.person];
return Object.assign(rooms, {
[idx === -1 ? rooms.length : idx]: room
});
}, []);
console.log(res);

How union arrays with validate only one property

Joining of Arrays.
I'm in need of running a "Join Array" objects, but, I need duplicated objects to be removed, see:
Example
var objArray1 = [
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 }
];
var objArray2 = [
{ Id: 2, Name: 'Pedro', Order: 6 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
Actual code:
var result = _.union(objArray1,objArray2);
=> [
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 },
{ Id: 2, Name: 'Pedro', Order: 6 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
I need this result:
[
{ Id: 1, Name: 'João', Order: 2 },
{ Id: 2, Name: 'Pedro', Order: 5 },
{ Id: 3, Name: 'Manoel', Order: 9 }
];
Basic I need join arrays with filter the one property, I need is possible with For but I would like a better solution
use underscore unique function as follows
var result = _.uniq(_.union(objArray1, objArray2), false, function(item){ return item.Id; });
not 100% sure if the false should be true
or, as seems to be a trend on SO - the sexy ES2015 version
var result = _.uniq(_.union(objArray1, objArray2), false, item => item.Id);

Categories

Resources