I have a CLI App that scraps 5 different deals page and save it into ##all class variable. I want all of them to have a new variable which should start from 1 to 100(because there are total 100 deals). I tried a lot but it just shows number 1 for all the deals.
def deals_listing
all_deals = PopularDeals::NewDeals.all
#deals = []
all_deals.collect do |deal_info|
i = 1
deal_info.number = i
#deals << deal_info
i = i + 1
end
#deals
binding.pry
end
The sample of output that I am getting is..
pry(#<PopularDeals::CLI>)> #deals
=> [#<PopularDeals::NewDeals:0x00000001aaf220
#deal_rating="+7",
#number=1,
#posted="Posted Today",
#price="$7.64",
#title=
"Back Again at Amazon Campbell's Slow Cooker Sauces, Apple Bourbon Pulled Pork, 13 Ounce (Pack of 6) as low as $7.64 w/ Subscribe and Save S&S w/ Free Shipping",
#url=
"https://slickdeals.net/f/10033448-back-again-at-amazon-campbell-s-slow-cooker-sauces-apple-bourbon-pulled-pork-13-ounce-pack-of-6-as-low-as-7-64-w-subscribe-and-save-s-
s-w-free-shipping">,
#<PopularDeals::NewDeals:0x00000001a876f8
#deal_rating="+6",
#number=1,
#posted="Posted Today",
#price="$5.33",
#title=
"LUCKLED 20 LED Solar Powered Dragonfly String Lights Multi-color $5.33 AC, FS w/prime #Amazon",
#url=
ing-lights-multi-color-5-33-ac-fs-w-prime-amazon">,
#<PopularDeals::NewDeals:0x00000001a84228
#deal_rating="+6",
#number=1,
#posted="Posted Today",
#price="$339.99",
#title=
ping # Walmart",
#url=
efurbished-339-99-free-shipping-walmart">,
#<PopularDeals::NewDeals:0x00000001a80ad8
#deal_rating="+6",
#number=1,
:
What I would like to have..
pry(#<PopularDeals::CLI>)> #deals
=> [#<PopularDeals::NewDeals:0x00000001aaf220
#deal_rating="+7",
#number=1,
#posted="Posted Today",
#price="$7.64",
#title=
"Back Again at Amazon Campbell's Slow Cooker Sauces, Apple Bourbon Pulled Pork, 13 Ounce (Pack of 6) as low as $7.64 w/ Subscribe and Save S&S w/ Free Shipping",
#url=
"https://slickdeals.net/f/10033448-back-again-at-amazon-campbell-s-slow-cooker-sauces-apple-bourbon-pulled-pork-13-ounce-pack-of-6-as-low-as-7-64-w-subscribe-and-save-s-
s-w-free-shipping">,
#<PopularDeals::NewDeals:0x00000001a876f8
#deal_rating="+6",
#number=2,
#posted="Posted Today",
#price="$5.33",
#title=
"LUCKLED 20 LED Solar Powered Dragonfly String Lights Multi-color $5.33 AC, FS w/prime #Amazon",
#url=
ing-lights-multi-color-5-33-ac-fs-w-prime-amazon">,
#<PopularDeals::NewDeals:0x00000001a84228
#deal_rating="+6",
#number=3,
#posted="Posted Today",
#price="$339.99",
#title=
ping # Walmart",
#url=
efurbished-339-99-free-shipping-walmart">,
#<PopularDeals::NewDeals:0x00000001a80ad8
#deal_rating="+6",
#number=4,
:
Any suggestions to make it work? Thank you so much in advance.
If you want to populate the property of an object with its position within some array:
#deals = PopularDeals::NewDeals.all.each_with_index.map do |deal, i|
deal.number = i
deal
end
That allows you to fetch, iterate, and assign in one pass with a minimal amount of mess. The each_with_index method gives you simple index for each element, and map allows you to convert that into your final array.
Well, this issue is solved. I got an answer. If anyone else is trying to do something like this, this is what I did.
def deals
all_deals = PopularDeals::NewDeals.all
#deals = []
all_deals.collect do |deal_info|
deal_info.number = all_deals.index(deal_info).to_i + 1
#deals << deal_info
end
#deals
end
I used .index method to find index number and added one to it so, it starts from 1, and assigned it to deal_info.number
Related
I have a column in database in which I store an array to store device specification in an array I think its array in a array now i want to get devices where for example technology 5G is Yes Value here is the below code and database entry of array
Array Of Specs in database
a:12:{s:6:"Launch";a:2:{s:9:"Announced";s:12:"2019, August";s:6:"Status";s:9:"Available";}s:7:"Network";a:7:{s:10:"Technology";s:35:"GSM / CDMA / HSPA / EVDO / LTE / 5G";s:2:"3G";s:3:"Yes";s:2:"4G";s:3:"Yes";s:2:"5G";s:3:"Yes";s:5:"Speed";s:69:"HSPA 42.2/5.76 Mbps, LTE-A (7CA) Cat20 2048/150 Mbps, 5G (2+ Gbps DL)";s:4:"Edge";s:3:"Yes";s:4:"GPRS";s:3:"Yes";}s:4:"Body";a:5:{s:10:"Dimensions";s:45:"162.3 x 77.2 x 7.9 mm (6.39 x 3.04 x 0.31 in)";s:6:"Weight";s:15:"198 g (6.98 oz)";s:3:"SIM";s:3:"Yes";s:5:"Build";s:75:"Glass front (Gorilla Glass 6), glass back (Gorilla Glass 6), aluminum frame";s:6:"Others";s:143:"Samsung Pay (Visa, MasterCard certified) IP68 dust/water resistant (up to 1.5m for 30 mins) Stylus (Bluetooth integration, accelerometer, gyro)";}s:7:"Display";a:6:{s:4:"Type";s:49:"Dynamic AMOLED capacitive touchscreen, 16M colors";s:4:"Size";s:51:"6.8 inches, 114.0 cm2 (~91.0% screen-to-body ratio)";s:10:"Resolution";s:49:"1440 x 3040 pixels, 19:9 ratio (~498 ppi density)";s:10:"Multitouch";s:3:"Yes";s:10:"Protection";s:23:"Corning Gorilla Glass 6";s:6:"Others";s:25:"HDR10+, Always-on display";}s:8:"Platform";a:4:{s:2:"OS";s:60:"Android 9.0 (Pie), planned upgrade to Android 10.0; One UI 2";s:7:"Chipset";s:31:"Exynos 9825 (7 nm) - EMEA/LATAM";s:3:"CPU";s:80:"Octa-core (2x2.73 GHz Mongoose M4 & 2x2.4 GHz Cortex-A75 & 4x1.9 GHz Cortex-A55)";s:3:"GPU";s:26:"Mali-G76 MP12 - EMEA/LATAM";}s:6:"Memory";a:2:{s:9:"Card Slot";s:36:"microSD, up to 1 TB (dedicated slot)";s:8:"Internal";s:30:"256GB 12GB RAM, 512GB 12GB RAM";}s:6:"Camera";a:4:{s:7:"Primary";s:68:"12 MP, f/1.5-2.4, 27mm (wide), 1/2.55", 1.4µm, Dual Pixel PDAF, OIS";s:8:"Features";s:29:"LED flash, auto-HDR, panorama";s:5:"Video";s:107:"2160p#30/60fps, 1080p#30/60/240fps, 720p#960fps, HDR10+, dual-video rec., stereo sound rec., gyro-EIS & OIS";s:9:"Secondary";s:57:"10 MP, f/2.2, 26mm (wide), 1/3", 1.22µm, Dual Pixel PDAF";}s:5:"Sound";a:4:{s:11:"Alert types";N;s:11:"Loudspeaker";s:3:"Yes";s:9:"3.5mmJack";s:3:"Yes";s:6:"Others";s:95:"32-bit/384kHz audio Active noise cancellation with dedicated mic Dolby Atmos sound Tuned by AKG";}s:5:"Comms";a:6:{s:4:"WLAN";s:60:"Wi-Fi 802.11 a/b/g/n/ac/ax, dual-band, Wi-Fi Direct, hotspot";s:9:"Bluetooth";s:19:"5.0, A2DP, LE, aptX";s:3:"GPS";s:38:"Yes, with A-GPS, GLONASS, BDS, GALILEO";s:3:"NFC";s:3:"Yes";s:5:"Radio";s:28:"FM radio (USA & Canada only)";s:3:"USB";s:36:"3.1, Type-C 1.0 reversible connector";}s:8:"Features";a:5:{s:7:"Sensors";s:91:"Fingerprint (under display, ultrasonic), accelerometer, gyro, proximity, compass, barometer";s:9:"Messaging";N;s:7:"Browser";N;s:4:"Java";N;s:6:"Others";N;}s:7:"Battery";a:4:{s:7:"Battery";s:37:"Non-removable Li-Ion 4300 mAh battery";s:8:"Stand-by";N;s:9:"Talk time";N;s:10:"Music play";N;}s:4:"Misc";a:5:{s:6:"Colors";s:33:"Aura Glow, Aura White, Aura Black";s:6:"SAR US";N;s:6:"SAR EU";N;s:11:"Price group";s:43:"€ 1,232.07 / $ 1,257.20 / £ 780.00";s:7:"Website";N;}}
Now the Query That i used in controller
public function technologynetwork(Request $request)
{
$tech = $request->a;
// return $tech;
$devices = DB::table('devices')
->select('devices.*')
->from('devices', 'specs_array')
->where('specs_array','===', array_search("Yes",specs_array))
->orderBy('release_year', 'desc')
->orderBy('release_month', 'desc')
->orderBy('id', 'desc')
->paginate(30);
return view('frontend/'.$this->config->template.'/devices', [
// global variables
'config' => $this->config,
'template_path' => $this->template_path,
'logged_user_role' => $this->logged_user_role ?? NULL,
// page variables
'devices' => $devices,
'count_all' => $devices->total(),
]);
}
and my route is in web.php
Route::get('/spec/{a}', 'Frontend\DevicesController#technologynetwork');
and its frontend
<dd>5G Phones</dd>
Anyone who can guide me how i can get any specs wise devices or how to search from an array
Could not decode your Array Of Specs in database.
Assume you save specs in a column field called specs_array, it has this format: "5G":"Yes"
public function technologynetwork(Request $request)
{
$tech = $request->a;
$search_string = '%"' . $tech . '":"Yes"%'; // = %"5G":"Yes"%
$devices = DB::table('devices')
->select('devices.*') // should remove this, not necessary
->from('devices', 'specs_array') // should remove this, not necessary
->where('specs_array','LIKE', $search_string) // <= use LIKE for query
->orderBy('release_year', 'desc')
->orderBy('release_month', 'desc')
->orderBy('id', 'desc')
->paginate(30);
return view('frontend/'.$this->config->template.'/devices', [
// global variables
'config' => $this->config,
'template_path' => $this->template_path,
'logged_user_role' => $this->logged_user_role ?? NULL,
// page variables
'devices' => $devices,
'count_all' => $devices->total(),
]);
}
When saving to database, spec_arrays becomes a string and should not be treated as array.
I like to sort my XML response.
This is my code:
// Make some cURL
// Create a simple XML element
$xml = new SimpleXMLElement($resp, LIBXML_NOWARNING, false);
// Output
foreach ($xml->Departure as $departure){
// DEFINE VARIABLES BASED ON XML RESPONSE
$name = $departure['name'];
$rtDate = $departure['rtDate'];
$rtTime = $departure['rtTime'];
$direction = $departure['direction'];
$trainCategory = $departure['trainCategory'];
// CALCULATE DURATION UNTIL NEXT DEPARTURE
$prognosedTime = new DateTime($rtTime);
$currentTime = new DateTime($time);
$interval = $currentTime->diff($prognosedTime);
// OUTPUT FOR BROWSERS
echo $interval->format('%i') . ' Min: ' . $name . ' > ' . $direction . '",';
echo $trainCategory;
echo "<hr/>";
};
?>
Result:
7 Min: Bus 240 > S Ostbahnhof
Bus
-------------------------------------
8 Min: Tram M10 > S+U Warschauer Str.
MetroTram
-------------------------------------
2 Min: U1 > Uhlandstr.
U-Bahn
-------------------------------------
0 Min: Tram M10 > S+U Hauptbahnhof
MetroTram
Problem:
My result should be sorted by $interval
I read
PHP sorting issue with simpleXML several times but I don't get it. So I wanted a shorter solution (for bloody beginners) and found something nice in Sort Foreach Loop after ID. But then I need arrays. Another solution is very close to that and shows how to define arrays: ASC sort foreach. But here I have no idea how to put all my data into an array as I never know how many rows the response will have. I believe I am very close to a solution but don't get it since 2 days. narf
I have a string like that: "Men's Beech River Cable T-Shirt" how can I get category from this string?
str = "Men's Beech River Cable T-Shirt"
str2 = "MEN'S GOOSE EYE MOUNTAIN DOWN VEST"
cat1 = str1.split.last # T-Shirt
cat2 = str2.split.last # VEST
TOPS = %w(jacket vest coat blazer parka sweater shirt polo t-shirt)
Desired result:
category_str1 = "Tops" # Since T-Shirt (shirt) is in TOPS constant.
category_str2 = "Tops" # Since vest is in TOPS const.
I don't know how to describe my problem better, I hope you understand it from example provided.
str = "Men's Beech River Cable T-Shirt"
cat_orig = str.split.last # T-Shirt
TOPS = %w(jacket vest coat blazer parka sweater shirt polo)
RE_TOPS = Regexp.union(TOPS)
category = "Tops" if RE_TOPS =~ cat_orig.downcase
Note there are no comma's in the %w() style array syntax.
str = "Men's Beech River Cable T-Shirt"
cat_orig = str.split.last # T-Shirt
TOPS = %w(jacket vest coat blazer parka sweater shirt polo) # suppressed the comma to get a clean array
category = "Tops" if !cat_orig[/(#{TOPS.join("|")})/i].nil?
The join on the TOPS Array build an alternative regex of the form:
(jacket|vest|coat|blazer|parka|sweater|shirt|polo)
If any of those word is present in cat_orig, the return will be the matched word, if not it will return nil.
Note the leading i in the regex to makes it case insensitive.
The best way to do this is through a hash, not an array. Let's say your caetgories look something like this
categories = { "TOPS" => ["shirt", "coat", "blazer"],
"COOKING" => ["knife", "fork", "pan"] }
We can then loop through each category and find if their values include the word in the string
categories.each do |key, value|
puts key if str.downcase.split(' ').any? { |word| categories[key].include?(word) }
end
Loop through each category, and find if the category has a word that the string has.
Note: This does not yet search for substrings.
Is it possible to create an Array from another Array?
Lang: Ruby on Rails
Case
Workers are entitled to fill in their own work hours. Sometimes they forget to do it. This is what I want to tackle. In the end, I want an Array with time codes of periods the worker forgot to register his hours.
timecodes = [201201, 201202, 201203, 201204, 201205, 201206, 201207, 201208, 201209, 201210, 201211, 201212, 201213, 201301, 201302, 201304, 201305, 201306, ...]
Worker works from 201203 to 201209 with us.
timecards = [201203, 201204, 201205, 201207, 201208, 201209]
As you see, he forgot to register 201206.
What I want to do
# Create Array from timecode on start to timecode on end
worked_with_us = [201203, 201204, 201205, 201206, 201207, 201208, 201209]
#=> This is the actual problem, how can I automate this?
forgot_to_register = worked_with_us.?????(timecards)
forgot_to_register = worked_with_us - timecards # Thanks Zwippie
#=> [201206]
Now I know which period the worker forgot to register his hours.
All together
How can I create an Array from another Array, giving a start and end value?
You can just subtract arrays with - (minus):
[1, 2, 3] - [1, 3] = [2]
To build an array with years/months, this can be done with a Range, but this only works if you build an array for each year, something like:
months = (2012..2013).map do |year|
("#{year}01".."#{year}12").to_a.collect(&:to_i)
end.flatten
=> [201201, 201202, 201203, 201204, 201205, 201206, 201207, 201208, 201209, 201210, 201211, 201212, 201301, 201302, 201303, 201304, 201305, 201306, 201307, 201308, 201309, 201310, 201311, 201312]
And for the function to create those ranges dynamically:
def month_array(year_from, year_to, month_from=1, month_to=12)
(year_from..year_to).map do |year|
# Correct from/to months
mf = year_from == year ? month_from : 1
mt = year_to == year ? month_to : 12
(mf..mt).map do |month|
("%d%02d" % [year, month]).to_i
end
end.flatten
end
Update: You wanted other input parameters for this method, but I hope you can work that out yourself. :)
I know this is probably dead simple, but I've got some data such as this in one file:
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
that I'd like to be able to format into a nice TSV type of table, to look something like this:
Name | Varieties | Container Data
----------|------------- |-------
some data here nicely padded with even spacing and right aligned text
Try String#rjust(width):
"hello".rjust(20) #=> " hello"
I wrote a gem to do exactly this: http://tableprintgem.com
No one has mentioned the "coolest" / most compact way -- using the % operator -- for example: "%10s %10s" % [1, 2]. Here is some code:
xs = [
["This code", "is", "indeed"],
["very", "compact", "and"],
["I hope you will", "find", "it helpful!"],
]
m = xs.map { |_| _.length }
xs.each { |_| _.each_with_index { |e, i| s = e.size; m[i] = s if s > m[i] } }
xs.each { |x| puts m.map { |_| "%#{_}s" }.join(" " * 5) % x }
Gives:
This code is indeed
very compact and
I hope you will find it helpful!
Here is the code made more readable:
max_lengths = xs.map { |_| _.length }
xs.each do |x|
x.each_with_index do |e, i|
s = e.size
max_lengths[i] = s if s > max_lengths[i]
end
end
xs.each do |x|
format = max_lengths.map { |_| "%#{_}s" }.join(" " * 5)
puts format % x
end
This is a reasonably full example that assumes the following
Your list of products is contained in a file called veg.txt
Your data is arranged across three lines per record with the fields on consecutive lines
I am a bit of a noob to rails so there are undoubtedly better and more elegant ways to do this
#!/usr/bin/ruby
class Vegetable
##max_name ||= 0
##max_variety ||= 0
##max_container ||= 0
attr_reader :name, :variety, :container
def initialize(name, variety, container)
#name = name
#variety = variety
#container = container
##max_name = set_max(#name.length, ##max_name)
##max_variety = set_max(#variety.length, ##max_variety)
##max_container = set_max(#container.length, ##max_container)
end
def set_max(current, max)
current > max ? current : max
end
def self.max_name
##max_name
end
def self.max_variety
##max_variety
end
def self.max_container()
##max_container
end
end
products = []
File.open("veg.txt") do | file|
while name = file.gets
name = name.strip
variety = file.gets.to_s.strip
container = file.gets.to_s.strip
veg = Vegetable.new(name, variety, container)
products << veg
end
end
format="%#{Vegetable.max_name}s\t%#{Vegetable.max_variety}s\t%#{Vegetable.max_container}s\n"
printf(format, "Name", "Variety", "Container")
printf(format, "----", "-------", "---------")
products.each do |p|
printf(format, p.name, p.variety, p.container)
end
The following sample file
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
Potatoes
King Edward, Desiree, Jersey Royal
36" wide x 8-10" deep
Produced the following output
Name Variety Container
---- ------- ---------
Artichoke Green Globe, Imperial Star, Violetto 24" deep
Beans, Lima Bush Baby, Bush Lima, Fordhook, Fordhook 242 12" wide x 8-10" deep
Potatoes King Edward, Desiree, Jersey Royal 36" wide x 8-10" deep
another gem: https://github.com/visionmedia/terminal-table
Terminal Table is a fast and simple, yet feature rich ASCII table generator written in Ruby.
I have a little function to print a 2D array as a table. Each row must have the same number of columns for this to work. It's also easy to tweak to your needs.
def print_table(table)
# Calculate widths
widths = []
table.each{|line|
c = 0
line.each{|col|
widths[c] = (widths[c] && widths[c] > col.length) ? widths[c] : col.length
c += 1
}
}
# Indent the last column left.
last = widths.pop()
format = widths.collect{|n| "%#{n}s"}.join(" ")
format += " %-#{last}s\n"
# Print each line.
table.each{|line|
printf format, *line
}
end
Kernel.sprintf should get you started.