How to merge array of hashes based on hash value but not merge values instead override - ruby

I have an array of hashes like this:
[
{ name: 'Pratha', email: 'c#f.com' },
{ name: 'John', email: 'j#g.com' },
{ name: 'Clark', email: 'x#z.com' },
]
And this is second group array of hashes:
[
{ name: 'AnotherNameSameEmail', email: 'c#f.com' },
{ name: 'JohnAnotherName', email: 'j#g.com' },
{ name: 'Mark', email: 'd#o.com' },
]
What I want is, merge these two arrays into one, merge based on :email and keep latest (or first) :name.
Expected Result (latest name overrided):
[
{ name: 'AnotherNameSameEmail', email: 'c#f.com' },
{ name: 'JohnAnotherName', email: 'j#g.com' },
{ name: 'Mark', email: 'd#o.com' },
{ name: 'Clark', email: 'x#z.com' },
]
or (first name preserved)
[
{ name: 'Pratha', email: 'c#f.com' },
{ name: 'John', email: 'j#g.com' },
{ name: 'Mark', email: 'd#o.com' },
{ name: 'Clark', email: 'x#z.com' },
]
So, basically, I want to group by :email, retain one :name, drop dupe emails.
The examples found on SO is creates an array of values for :name.
Ruby 2.6.3

Maybe you could just call Array#uniq with a block on email key of the concatenation (Array#+) of the two arrays:
(ary1 + ary2).uniq { |h| h[:email] }

a1 = [
{ name: 'Pratha', email: 'c#f.com' },
{ name: 'John', email: 'j#g.com' },
{ name: 'Clark', email: 'x#z.com' },
]
a2 = [
{ name: 'AnotherNameSameEmail', email: 'c#f.com' },
{ name: 'JohnAnotherName', email: 'j#g.com' },
{ name: 'Mark', email: 'd#o.com' },
]
Let's first keep the last:
(a1+a2).each_with_object({}) { |g,h| h.update(g[:email]=>g) }.values
#=> [{:name=>"AnotherNameSameEmail", :email=>"c#f.com"},
# {:name=>"JohnAnotherName", :email=>"j#g.com"},
# {:name=>"Clark", :email=>"x#z.com"},
# {:name=>"Mark", :email=>"d#o.com"}]
To keep the first, do the same with (a1+a2) replaced with (a2+a1), to obtain:
#=> [{:name=>"Pratha", :email=>"c#f.com"},
# {:name=>"John", :email=>"j#g.com"},
# {:name=>"Mark", :email=>"d#o.com"},
# {:name=>"Clark", :email=>"x#z.com"}]

Related

how to order array evenly by property

I have the following array:
arr = [
{ name: 'Apple', store: 'A' },
{ name: 'Banana', store: 'A' },
{ name: 'Carrot', store: 'B' },
{ name: 'Potato', store: 'B' },
{ name: 'Tomato', store: 'A' }
]
I need to sort the array by switching between each store like this:
arr = [
{ name: 'Apple', store: 'A' },
{ name: 'Carrot', store: 'B' },
{ name: 'Banana', store: 'A' },
{ name: 'Tomato', store: 'B' },
{ name: 'Potato', store: 'A' }
]
How can I do that with ruby ?
I came up with something :)
arr = [
{ name: 'Apple', store: 'A' },
{ name: 'Banana', store: 'A' },
{ name: 'Carrot', store: 'B' },
{ name: 'Potato', store: 'B' },
{ name: 'Tomato', store: 'A' }
]
first, *rest = arr.group_by { |h| h[:store] }.values
first.zip(*rest).flatten.compact
See it in action: Replit

GraphQL + Sequalize + existing database - "message": "parent.getPages is not a function" for one model not the other

GraphQL Query
Morning all,
I have a nice setup GraphQL -> Sequalize -> Existing DB (generated by a Laravel application). I've built this schema out:
type App {
id: ID!
userId: ID
user: User
pages: [Page]
experiments: [Experiment]
uri: String!
createdAt: String!
updatedAt: String!
}
type Page {
id: ID!
userId: ID
user: User
appId: ID!
app: App!
uri: String!
createdAt: String!
updatedAt: String!
}
type Experiment {
id: ID!
title: String!
appId: ID!
app: App!
createdAt: String!
updatedAt: String!
}
Based on the existing data. Querying an apps experiments works just great:
query {
app(id: 6) {
id
title
experiments {
id
}
}
}
{
"data": {
"app": {
"id": "6",
"title": "C-Map Embark: Boating",
"experiments": [
{
"id": "1"
}
]
}
}
}
But querying pages I get this:
query {
app(id: 6) {
id
title
pages {
id
}
}
}
{
"errors": [
{
"message": "parent.getPages is not a function",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"app",
"pages"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: parent.getPages is not a function",
...
The db columns are the same, as are the resolvers:
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
const Page = sequelize.define(
"page",
{
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
...
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
},
{
tableName: "pages",
underscored: true
}
);
Page.associate = models => {
Page.belongsTo(models.app);
};
return Page;
};
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
const Experiment = sequelize.define(
"experiment",
{
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
...
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
},
{
tableName: "experiments",
underscored: true
}
);
Experiment.associate = models => {
Experiment.belongsTo(models.app);
};
return Experiment;
};
Have you come across this before?

Botkit - Slack interactive messages

I am trying to get all the values from all actions. Currently I have two select actions (Pick a game and Pick a day). In the interactive_messages_callback I am getting the selected value only of the currently modified select.
Is there a way to get an array of values from all the actions like currentValues: [ os_type_selection: 'osx', day_selection: '2' ]?
bot.reply(message, {
attachments: [
{
title: 'Question 1',
callback_id: 'question_1',
attachment_type: 'default',
actions: [
{
name: 'os_type_selection',
text: 'Pick a game...',
type: 'select',
options: [
{
text: 'Mac OS X',
value: 'osx',
},
{
text: 'Windows',
value: 'windows',
}
]
}
],
},
{
title: 'Question 2',
callback_id: 'question_2',
attachment_type: 'default',
actions: [
{
name: 'day_selection',
text: 'Pick a day...',
type: 'select',
options: [
{
text: 'Monday',
value: '1',
},
{
text: 'Tuesday',
value: '2',
},
]
},
],
},
],
});
// interactive_messages_callback
{ type: 'interactive_message_callback',
actions:
[ { name: 'day_selection',
type: 'select',
selected_options: [Object] } ],
callback_id: 'question_2',
team: { id: 'T02L9R6LX', domain: 'hellephant' },
channel: 'D9066R5NC',
user: 'U4C2DDM9T',
action_ts: '1517489936.972094',
message_ts: '1517489928.000257',
attachment_id: '2',
token: 'f5LpbwCQ2D97BhNOPgn1Gotb',
is_app_unfurl: false,
original_message:
{ type: 'message',
user: 'U90RBPAE6',
text: '...',
bot_id: 'B90UUGKSR',
attachments: [ [Object], [Object] ],
ts: '1517489928.000257' },
response_url: 'https://hooks.slack.com/actions/T02L9R6LX/309104841078/xsmwspjpdhV1oSW06PQkQZp5',
trigger_id: '308368498005.2689856711.9425688de7f023516061a4e4b2701322',
raw_message:
{ type: 'interactive_message',
actions: [ [Object] ],
callback_id: 'question_2',
team: { id: 'T02L9R6LX', domain: 'hellephant' },
channel: { id: 'D9066R5NC', name: 'directmessage' },
user: { id: 'U4C2DDM9T', name: 'davidnovak' },
action_ts: '1517489936.972094',
message_ts: '1517489928.000257',
attachment_id: '2',
token: 'f5LpbwCQ2D97BhNOPgn1Gotb',
is_app_unfurl: false,
original_message:
{ type: 'message',
user: 'U90RBPAE6',
text: '...',
bot_id: 'B90UUGKSR',
attachments: [Object],
ts: '1517489928.000257' },
response_url: 'https://hooks.slack.com/actions/T02L9R6LX/309104841078/xsmwspjpdhV1oSW06PQkQZp5',
trigger_id: '308368498005.2689856711.9425688de7f023516061a4e4b2701322' },
_pipeline: { stage: 'receive' },
text: '2' }
No. You can not have multiple interactive menus on the same message in Slack. Its technically possible, but once the user selects one menu it will always fire for that menu, making it impossible for the user to select from multiple menus at the same time.
If you want to use multiple menus you need to spread them out over separate messages and let the user select one after the other.
Or check out the dialog function, which allows you to use multiple menus at the same time.

ng-repeat orderby of dynamic lenght of object

I have the following object that contains 2 fixed attributes (OrderId and Purchasedate, and an array of attribues. I try to to put this in ng-repeat with orderBy option. The first 2 attribute (OrderId and PurchaseDate) work OK when sorting is applied by clicking on the header. However I do not get it working on the 3 rd attribute and so on.
The rows shown on the table are correct.
The object looks like
e.g.
$scope.orders;
[
{ OrderId: "P888291", PurchaseDate : "2016-12-02",
Items: { elt : [ { Name: "City", Value: "New York"}, { Name: "Street", Value: "Broadway 5" }, { Name: "Country", Value: "USA" } ] } },
{ OrderId: "P334498", PurchaseDate : "2016-11-02",
Items: { elt : [ { Name: "City", Value: "London" }, { Name: "Street", Value: "WestMinister 3" }, { Name: "Country", Value: "Great Brittain" } ] } },
{ OrderId: "G393383", PurchaseDate : "2016-11-28",
Items: { elt : [ { Name: "City", Value: "Milan" }, { Name: "Street", Value: "Pizza 8" }, { Name: "Country", Value: "Italy" } ] } },
{ OrderId: "P978381", PurchaseDate : "2015-05-25",
Items: { elt : [ { Name: "City", Value: "Seattle" }, { Name: "Street", Value: "Houston 9" }, { Name: "Country", Value: "US" } ] } },
{ OrderId: "P983394", PurchaseDate : "2015-06-05",
Items: { elt : [ { Name: "City", Value: "Amsterdam" }, { Name: "Street", Value: "Damrak 5" }, { Name: "Country", Value: "Netherlands" } ] } },
{ OrderId: "G678994", PurchaseDate : "2015-04-01",
Items: { elt : [ { Name: "City", Value: "The Hague" }, { Name: "Street", Value: "Markt 22" }, { Name: "Country", Value: "Netherlands" } ] } },
{ OrderId: "P128994", PurchaseDate : "2016-12-04",
Items: { elt : [ { Name: "City", Value: "The Hague" }, { Name: "Street", Value: "Plein 7" }, { Name: "Country", Value: "Netherlands" } ] } },
];
Please advise and the code is put in :
http://www.w3schools.com/code/tryit.asp?filename=FAG7BWVK8BYH
You can try with custom filter logic.(https://docs.angularjs.org/api/ng/filter/orderBy )
for example:
JS:
$scope.filterOrderFn = function(orderobj)
{
// Do
if(...)
{
return _something_// this will be your sorted order according to your first condition
}
else if(...)
{
return _something_ // this will be your sorted order according to your second condition if require
}
return false; // otherwise it won't be within the orderlist
};
HTML:
...
<article data-ng-repeat="order in orders | orderBy:filterOrderFn" class="order">
...
If you need a very specific ordering behaviour you could write your own filter (although orderBy should be enough for most uses cases). As you may know you can chain many filters together, so adding your custom filter function doesn't force you to remove the previous filter using the search object (they will work together seamlessly).

Ruby map specific hash keys to new one

I've got an array full of hashes of which I want to combine specific keys to a new one, e.g.
[{ firstname: 'john', lastname: 'doe', something: 'else', key: ... }, { firstname: 'Joe', lastname: 'something', something: 'bla', key:... }]
should become
[{ name: 'john doe' },{ name: 'Joe something' }]
Please note: there are more keys in the hash as first and lastname. Is there a common ruby method to do this? Thanks!
Just do as
array = [{ firstname: 'john', lastname: 'doe' }, { firstname: 'Joe', lastname: 'something' }]
array.map { |h| { :name => h.values_at(:firstname, :lastname) * " " } }
# => [{:name=>"john doe"}, {:name=>"Joe something"}]
Read this Hash#values_at and Array#* .
This is:
a = [{ firstname: 'john', lastname: 'doe' }, { firstname: 'Joe', lastname: 'something' }]
a.map { |n| { name: n.values.join(' ') } }
# => [{:name=>"john doe"}, {:name=>"Joe something"}]

Resources