I have the following hashes:
#valids
[
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
}
]
#invalids
[
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => nil,
:email => "roger#gmail.com",
:fname => nil
}
]
What I'm going to be doing is looping through the invalids, and if an email meets a certain criteria, I want to move that item to valids and then remove it from invalids.
Example, while looping through #invalids, if the email = roger#gmail.com, I want to take:
{
:lname => nil,
:email => "roger#gmail.com",
:fname => nil
}
And move it to #valids, and remove it from #invalids.
Is there a way to do this without having to create new hashes? Thanks
This should do it:
#invalids = #invalids.reject do |record|
if record[:email] == "roger#gmail.com"
#valids.push(record)
end
end
To explain it a little bit, I'm setting #invalids as the result of running
#invalids.reject and passing it a block, so it will reject any array item that meets the criteria (returns something truish).
Inside the conditional I add to the #valids array
Related
I have a mongoid criteria categories and I need to convert to an array. I'm using categories.to_a but this dont works and always that the mongoid criteria is iterate by .map it's doing a .find a new query.
How can I fix this?
def self.mapOffers (array, user)
array.map { |u|
{
:id => u.id.to_s,
:name => u.name,
:description => u.description,
:price => u.price,
:url => u.url,
:categories => Category.mapCategories(u.categories.to_a, user),
:picture => u.picture.url,
:accepts_cash => u.accepts_cash_transactions,
:location => {
:longitude => u.longitude,
:latitude => u.latitude,
:street => u.street,
:neighborhood => u.neighborhood,
:number => u.number,
:zip => u.zip,
:city => u.city,
:state => u.state,
:complement => u.complement,
:country => u.country,
},
:fixedMeetingPoint => u.fixedMeetingPoint,
:meetingPoint => {
:street => u.meetingPointStreet,
:neighborhood => u.meetingPointNeighborhood,
:number => u.meetingPointNumber,
:zip => u.meetingPointZip,
:city => u.meetingPointCity,
:state => u.meetingPointState,
:complement => u.meetingPointComplement,
:country => u.meetingPointCountry,
:latitude => u.meetingPointLatitude,
:longitude => u.meetingPointLongitude,
},
:notes => u.notes,
}}
end
def self.mapCategories (array, user)
array.map { |u| {
:id => u.id.to_s,
:name => u.name,
:selected => !user.nil? && u.users.include?(user),
:picture => u.picture.url,
}}
end
Starting from criteria:
scope = Band.where(name: 'foo')
... retrieve the complete result set from the database and store in an array:
bands = scope.to_a
... then iterate the array any number of times:
bands.each { |band| ... }
bands.each { |band| ... }
I would need to access the array to retrieve the information and insert it into the database (Code, Customer, Phone1, Phone2). Someone can help me?
{
:recordset => {
:row => [
[0] {
:property => [
[0] {
:name => "Code",
:value => "C0001"
},
[1] {
:name => "Customer",
:value => "ROSSI MARIO"
},
[2] {
:name => "Phone1",
:value => "1234567890"
}
]
},
[1] {
:property => [
[0] {
:name => "Code",
:value => "C0002"
},
[1] {
:name => "Customer",
:value => "VERDE VINCENT"
},
[2] {
:name => "Phone1",
:value => "9876543210"
},
[3] {
:name => "Phone2",
:value => "2468101214"
}
]
}
]
},
:#xmlns => "http://localhost/test"
}
p.s. The Phone2 value during the SOAP call is only displayed if it is present in an archive
Thank you
Your data doesn't look like a valid ruby structure. Once you are able to convert it to be more ruby-like, you can make use of each_with_object to generate a well formatted set of attributes and their values from your data:
data
=> {:recordset=>{
:row=>[{
:property=>[
{:name=>"Code", :value=>"C0001"},
{:name=>"Customer", :value=>"ROSSI MARIO"},
{:name=>"Phone1", :value=>"1234567890"}
]
}, {
:property=>[
{:name=>"Code", :value=>"C0002"},
{:name=>"Customer", :value=>"VERDE VINCENT"},
{:name=>"Phone1", :value=>"9876543210"},
{:name=>"Phone2", :value=>"2468101214"}
]
}]
},
:#xmlns=>"http://localhost/test"}
data.keys
=> [:recordset, :#xmlns]
data[:recordset][:row].count
=> 2 # There are 2 set of attribute-value pairs
result = data[:recordset][:row].each_with_object([]) do |hash, out|
out << hash[:property].each_with_object({}) do |h, o|
o[h[:name]] = h[:value]
end
end
=> [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
{"Code"=>"C0002", "Customer"=>"VERDE VINCENT", "Phone1"=>"9876543210", "Phone2"=>"2468101214"}]
Now, you can iterate over result and create respective records in database.
I'm trying to take everything out of my Users table and send it to mail chimp for subscription.
I need to go from User.all to
[{:email => {:email => "example#domain.org"},
:merge_vars => {:FNAME => "First name", :LNAME => "Last name"}
}]
I'm trying to do this with map but I'm struggling, any ideas of the cleanest way of doing this?
subscription_array = User.all.collect do |user|
{
:email => {:email => user.email},
:merge_vars => {:FNAME => user.first_name, :LNAME => user.last_name}
}
end
users_array = []
User.all.find_each {|u| users_array << {:email => u.email, :merge_vars => {:FNAME => u.first_name, :LNAME => u.last_name} }
I chose to use find_each is it's a more efficient way of loading your collection.
http://api.rubyonrails.org/classes/ActiveRecord/Batches.html
I have a hash like so:
[
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
}
]
What I would like to learn how to do is how to remove a record if it is duplicate. Meaning, see how there are several "brad#intuit.com" how can I remove the duplicate records, meaning remove all the others that have an email of "brad#intuit.com".... Making email the key not the other fields?
In Ruby 1.9.2, Array#uniq will accept a block paramater which it will use when comparing your objects:
arrays.uniq { |h| h[:email] }
I know this is an old thread, but Rails has a method on 'Enumerable' called 'index_by' which can be handy in this case:
list = [
{
:lname => "Brown",
:email => "james#intuit.com",
:fname => "James"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
},
{
:lname => "Smith",
:email => "brad#intuit.com",
:fname => "Brad"
},
{
:lname => nil,
:email => "brad#intuit.com",
:fname => nil
}
]
Now you can get the unique rows as follows:
list.index_by {|r| r[:email]}.values
To merge the rows with the same email id.
list.group_by{|r| r[:email]}.map do |k, v|
v.inject({}) { |r, h| r.merge(h){ |key, o, n| o || n } }
end
Custom but efficient method:
list.inject({}) do |r, h|
(r[h[:email]] ||= {}).merge!(h){ |key, old, new| old || new }
r
end.values
If you're putting this directly into the database, just use validates_uniqueness_of :email in your model. See the documentation for this.
If you need to remove them from the actual hash before being used then do:
emails = [] # This is a temporary array, not your results. The results are still in my_array
my_array.delete_if do |item|
if emails.include? item[:email]
true
else
emails << item[:email]
false
end
end
UPDATE:
This will merge the contents of duplicate entries
merged_list = {}
my_array.each do |item|
if merged_list.has_key? item[:email]
merged_list[item.email].merge! item
else
merged_list[item.email] = item
end
end
my_array = merged_list.collect { |k, v| v }
Ok, this (delete duplicates) is what you asked for:
a.sort_by { |e| e[:email] }.inject([]) { |m,e| m.last.nil? ? [e] : m.last[:email] == e[:email] ? m : m << e }
But I think this (merge values) is what you want:
a.sort_by { |e| e[:email] }.inject([]) { |m,e| m.last.nil? ? [e] : m.last[:email] == e[:email] ? (m.last.merge!(e) { |k,o,n| o || n }; m) : m << e }
Perhaps I'm stretching the one-liner idea a bit unreasonably, so with different formatting and a test case:
Aiko:so ross$ cat mergedups
require 'pp'
a = [{:fname=>"James", :lname=>"Brown", :email=>"james#intuit.com"},
{:fname=>nil, :lname=>nil, :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"},
{:fname=>nil, :lname=>nil, :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"},
{:fname=>"Brad", :lname=>"Smith", :email=>"brad#intuit.com"}]
pp(
a.sort_by { |e| e[:email] }.inject([]) do |m,e|
m.last.nil? ? [e] :
m.last[:email] == e[:email] ? (m.last.merge!(e) { |k,o,n| o || n }; m) :
m << e
end
)
Aiko:so ross$ ruby mergedups
[{:email=>"brad#intuit.com", :fname=>"Brad", :lname=>"Smith"},
{:email=>"james#intuit.com", :fname=>"James", :lname=>"Brown"}]
this one creates an error:
#settings = {
:tab1 => {
:name => {
:required => true
},
:description
}
}
need to change :descrpition to :description => {}, but i don't have any values for :description so i want it to remain as is (without the empty => {})
Would you show me the best way to handle this kind of situation?
thanks in advance
You can assign nil to it.
#settings = {
:tab1 => {
:name => {
:required => true
},
:description => nil
}
}
Ruby's Hash prior to 1.9 is not ordered, and even afterwards it's a bit clumsy, as AFAIK you can't reorder items etc., so if you also want to preserve the order of the elements, you may consider using array instead of hash:
#settings = {
:tab1 => [
{
:field => :name,
:required => true
},
{
:field => :description
}
]
}