1

i have two data,

{:date=>"2015-09-23", :time=>["13:30"]}
{:date=>"2015-09-23", :time=>["12:00"]}
...more

and i try to remove this from

{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-23", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}

and the output i hope can get

{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-23", :time=>["12:30", "13:00", "14:00", "14:30"]}
{:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}

i was try

removeAry.each do |b|
  if b[:date] == "2015-09-23"
    puts b[:time].to_s.delete("13:30")
  end
end

do have any better idea ?

2
  • I think you can always make life much easier if you always consider how to store your data according to you application needs. For example, if you have a an array of hashes as such: [{:"2015-09-21" => ["12:00", "12:30", "13:00", "13:30"]}. In this case you can traverse through you structure using array index and then grap your hash using key,value pairs. Key being the day, and value would be an array of time stamps. Commented Sep 21, 2015 at 11:27
  • because this data is created by different user and time Commented Sep 21, 2015 at 11:42

6 Answers 6

1

If you have control over how your data is represented then you might consider simplifying your data as such:

The data you want removed

{:"2015-09-23" => ["12:00", "13:30"]}

Data to be removed from

[{:"2015-09-21" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
 {:"2015-09-22" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
 {:"2015-09-23" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
 {:"2015-09-24" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

The output you want achieved

[{:"2015-09-21" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
 {:"2015-09-22" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
 {:"2015-09-23" => ["12:30", "13:00", "14:00", "14:30"]},
 {:"2015-09-24" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

By doing this you can now:

target = {:"2015-09-23" => ["12:00", "13:30"]}
input = [{:"2015-09-21" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
     {:"2015-09-22" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
     {:"2015-09-23" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
     {:"2015-09-24" => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

input.each do |hash|
  hash.each do |key, value|
    if key == target.keys[0]
      target.values.each do |t_value|
        hash[key].delete(t_value)
      end
    end
  end
end

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Please let me know if this doesn't fit your solution so I can enhance the answer. Thanks.
thanks, but i can't change the data format. and i try too many time, each time they delete all date time, for example, if i need delete "2015-09-23" "13:00", return will delete all date "13:00"
0

Ok, here's what I would do:

require 'set'

to_delete = [
  {:date=>"2015-09-23", :time=>["13:30"]},
  {:date=>"2015-09-23", :time=>["12:00"]}
]

data = [
  {:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
  {:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
  {:date=>"2015-09-23", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
  {:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
]

# convert to_delete array to a hash { "2015-09-23" => #<Set: {"13:30", "12:00"}> }
# we use Set here to store only unique time values
to_delete_as_hash = to_delete.reduce({}) do |acc, item|
  acc[item[:date]] ||= Set.new
  acc[item[:date]] += item[:time]
  acc
end

filtered = data.map do |item|
  # skip this item if there's no need to process this date
  next item unless to_delete_as_hash[item[:date]]
  # subtract to_delete values from current item[:time] values
  item[:time] -= to_delete_as_hash[item[:date]].to_a
  item
end

p filtered

Output:

[
    {:date => "2015-09-21", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
    {:date => "2015-09-22", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
    {:date => "2015-09-23", :time => ["12:30", "13:00", "14:00", "14:30"]},
    {:date => "2015-09-24", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
]

2 Comments

one more tricky question. how add condition, if [to_delete] data, no time, just date, need delete that date from data. i'm try modify code now, if you have any advance how to make it, please kind let me know. thanks you so much for your help.
It is not clear from your comment what input and output you want to achieve. Could you update your question with examples, just as you did the first time? Thank you.
0

First define your test data

data = [{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}, {:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}, {:date=>"2015-09-23", :time=>["12:30", "13:00", "14:00", "14:30"]}, {:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

to_delete = {:date=>"2015-09-23", :time=>["13:30"]}

Main code

data.select{|x| x if x[:date] == to_delete[:date]}.each{|x| x.delete(to_delete[:time])}

You can also store to_delete in array and iterate over it.

2 Comments

Why not data.select{|x| x[:date] == to_delete[:date]}? Select only cares if return value of a block is truthy, or am I wrong?
data.select{|x| x if x[:date] == to_delete[:date]}.each{|x| x.delete(to_delete[:time])} this not work, but data.select{|x| x if x[:date] == to_delete[0][:date]}.each{|x| x.delete(to_delete[0][:time])} why ?
0

I have rewrite your code as following

data = [{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}, 
        {:date=>"2015-09-22", :time=>["12:00", "12:30", 13:00", "13:30", "14:00", "14:30"]},
        {:date=>"2015-09-23", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
        {:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

And Function to manipulate hash

def output_hash(data, p_date="2015-09-23", p_time="13:30")
    output = data.collect do |key, value|
      if key[:date] == p_date
         key[:time].delete!(p_time) if key[:time].include?(p_time) 
         time =  key[:time]
         key.delete(:time)
         key.merge!(:time => time)
       else 
         key
       end
    end
    return output
end

will generate following output

 [{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}, 
  {:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
  {:date=>"2015-09-23", :time=>["12:00", "12:30", "13:00", "14:00", "14:30"]},
  {:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}]

2 Comments

how it work if have another date and another time ? like : {:date=>"2015-09-24", :time=>["14:30"]}
very simple you have to pass two params p_date and p_time, then use that into the function with rap a method name. See the edited answer rape with a method.
0

have a try:

removeAry.map { |h| h[:date] == "2015-09-23" ? (h[:time].delete("13:30");h) : h }

or:

def removeAry.function(date, time)
  self.map { |h| h[:date] == date ? (h[:time].delete(time);h) : h }
end

removeAry.function("2015-09-23", "13:30")

2 Comments

if have data with different date, like: {:date=>"2015-09-26", :time=>["12:00"]} this not work...
@user7331you can define a method, date and time as arguments.
0
hash = [
    {:date => "2015-09-21", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
    {:date => "2015-09-22", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
    {:date => "2015-09-23", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]},
    {:date => "2015-09-24", :time => ["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
]

comparables = [
    {:date => "2015-09-23", :time => ["13:30"]},
    {:date => "2015-09-23", :time => ["12:00"]}
]

hash.each do |new_hash|
  comparables.each do |comparable|
    if new_hash[:date] == comparable[:date]
      new_hash[:time] = new_hash[:time] - comparable[:time]
    end
  end
end

puts hash

Output

user@ubuntu:~$ ruby test.rb 
{:date=>"2015-09-21", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-22", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}
{:date=>"2015-09-23", :time=>["12:30", "13:00", "14:00", "14:30"]}
{:date=>"2015-09-24", :time=>["12:00", "12:30", "13:00", "13:30", "14:00", "14:30"]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.