loop through implicit array - arrays

I've been stuck on this for awhile now. I'm trying to loop through this array so I can perform some calculations but I cannot figure out how to loop through there values. Any suggestions?
I managed to figure out how to get there collection structures but I want to loop through each structure and grab there values as well and thats what I'm stuck on.
Also, I want to refrain from using cfscript if possible as I'm still in the learning stages of learning coldfusion.
Here is my code:
<cfset houseStuff = {
Bedroom = [
'Luxury Duvet Set with Alternative Down Comforter',
'Accent Coverlet & Shams',
'Two Sets of Luxurious Liens',
'Mattress Pad',
'Blanket',
'Six Bed Pillows',
'Clock Radio',
'Twenty Hangers'
],
Bathroom = [
'Four Bath Towels',
'Four Hand Towels',
'Four Face Towels',
'Bath Rug',
'Shower Curtain',
'Stainless Tooth Brush Holder & Soap Dish',
'Wastebasket',
'Artwork',
'Hair Dryer',
'Toilet Brush & Plunger'
],
Dining = [
'Dinnerware',
'Place Mats',
'Napkins',
'Flatware',
'Glassware & Wine Glasses'
],
Kitchen = [
'Microwave',
'Cookware',
'Mixing Bowls',
'Baking Dish',
'Colander',
'Stainless Utensil Holder',
'Large Fork',
'Large Spoon',
'Spatula',
'Whisk',
'Measuring Spoon & Cup',
'Carving & Paring Knives',
'Four Steak Knives',
'Cutting Board',
'Salt & Pepper Set',
'Wine Opener',
'Coffee Maker',
'Toaster',
'Electric Can Opener',
'Flatware Tray',
'Kitchen Wastebasket',
'Dish Towels',
'Pot Holders',
'Pitcher',
'10" Non-Stick Frying Pan',
'Cookie Sheet',
'Stainless Steel Electric Tea Kettle',
'3 Piece Non-Metal (Spatula, Spoon, Paste Spoon) Combo'
],
Micellaneous = [
'Iron & Cutting Board',
'Cordless Dual Phone with Digital Answering Machine',
'Broom',
'Dust Pan',
'Vacuum',
'Decor',
'Laundry Basket'
],
StarterKit = [
'Bath Tissue',
'Soap',
'Shampoo & Conditioner',
'Paper Towels',
'Sponge',
'Laundry Soap',
'Dishwasher Detergent',
'Liquid Dish Soap',
'Extra Light Bulbs',
'Coffee',
'Sugar',
'Creamer',
'Bottled Water',
'Oatmeal',
'Breakfast Bars',
'Peanuts',
'Chips',
'Mints',
'Welcome Information'
],
MasterBedroom = [
'Queen bed',
'Headboard',
'Two Nightstands',
'Dresser & Mirrior',
'Two Lamps',
'Artwork',
'LCD Television'
],
LivingRoom = [
'Sofa',
'Chair',
'End Table',
'Coffee Table',
'Lamp',
'LCD TV w/stand',
'DVD Player',
'Artwork'
],
DiningRoom = [
'Dining Table',
'Dining Chairs',
'Artwork'
],
OfficePackage = [
'Desk',
'Chair',
'Lamp'
],
AdditionalBedrooms = [
'Queen or Two Twin Beds',
'Headboard',
'Nightstand',
'Chest of Drawers',
'Lamp',
'Artwork'
]
} />
<cfloop collection="#houseStuff#" item="key">
<cfdump var="#key#"> <br>
<!--- <p style="color:##fff;">#key#:</p> <br /> --->
</cfloop>

Nevermind, I finally figured it out. I had to loop through the collection first. Once I do that create another loop inside it to loop over it's structured values.
<cfloop collection="houseStuff" item="key">
<!---<cfdump var="#houseStuff[key]"> --->
<cfloop from="1" to="#arrayLen(houseStuff[key])#" index="j">
#j#
</cfloop>
</cfloop>

I know you said you'd prefer tags instead of script, but if you are in the learning stages of ColdFusion, I'd still recommend learning how to properly use cfscript. In addition to making your CF a little bit cleaner, it will also make your life a lot easier, especially for things like looping.
Outputting all elements becomes:
<cfscript>
for ( i in houseStuff ) { // loop over the outer Structure
writeOutput(i & ":<br>") ;
for ( j in houseStuff[i] ) { // loop over each inner Array key
writeOutput(j & "<br>") ;
}
writeOutput("<br>");
}
</cfscript>
https://trycf.com/gist/898988f6969a57aa5dece39c42037cfd/acf?theme=monokai
... which, in this context, does get into the philosophical discussion of whether to write output code in tags or script and goes slightly beyond the scope of this question. But I've always been a proponent of learning best-practices at the same time as the basics. Personally, I do tend to follow the tags-for-output view, but for basic looping, the script version is a bit cleaner to me. I'd learn both.
Also check out: http://www.learncfinaweek.com. There's a section in there on Looping with both methods.

Related

In a Ruby on Rails app, I'm trying to loop through an array within a hash within an array. Why am I getting "syntax error" message?

I have a Ruby on Rails application to enter results and create a league table for a football competition.
I'm trying to input some results by creating records in the database through heroku and I get error messages.
The application isn't perfectly designed: to enter the results, I have to create the fixtures and enter the score for each team. Then, independently I have to record each goal scorer, creating a record for each goal which is either associated with an existing player or requires me to firstly create a new player and then create the goal.
When I ran the code below heroku, I got this error:
syntax error, unexpected ':', expecting keyword_end
Maybe I'm missing something simple about lopping through an array within a hash?
Thank you for any advice!
coalition = Team.find_by(name: "Coalition")
moscow_rebels = Team.find_by(name: "Moscow Rebels")
red_star = Team.find_by(name: "Red Star")
unsanctionables = Team.find_by(name: "The Unsanctionables")
cavalry = Team.find_by(name: "Cavalry")
galactics = Team.find_by(name: "The Galactics")
happy_sundays = Team.find_by(name: "Happy Sundays")
hardmen = Team.find_by(name: "Hardmen")
international = Team.find_by(name: "International")
evropa = Venue.find_by(name: "Evropa")
s28 = Season.find_by(number: 28)
start_time = DateTime.new(2020,9,6,11,0,0,'+03:00')
scheduled_matches_1 =
[
{team_1: cavalry, team_1_goals: 1, team_1_scorers: ["Minaev"], team_2_goals: 6, team_2_scorers: ["Kovalev", "Kovalev", "Kovalev", "Thomas", "Thomas", "Grivachev"], team_2: coalition, time: start_time, venue: evropa, season: s28},
{team_1: hardmen, team_1_goals: 4, team_1_scorers: ["Jones", "Jones", "Jones", "Fusi"], team_2_goals: 2, team_2_scorers: ["Kazamula", "Ario"], team_2: galactics, time: start_time + 1.hour, venue: evropa, season: s28},
{team_1: international, team_1_goals: 9, team_1_scorers: ["Kimonnen", "Kimonnen", "Kimonnen", "Burya", "Burya", "Zakharyaev", "Zakharyaev", "Lavruk", "Rihter"], team_2_goals: 0, team_2_scorers: [], team_2: happy_sundays, time: start_time+2.hours, venue: evropa, season: s28}
]
scheduled_matches.each do |match|
new_fixture = Fixture.create(time: match[:time], venue: match[:venue], season: match[:season])
tf1 = TeamFixture.create(team: match[:team_1], fixture: new_fixture)
tf2 = TeamFixture.create(team: match[:team_2], fixture: new_fixture)
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match{:team_1_goals})
ts2 = TeamScore.create(team_fixture: tf2, total_goals: match{:team_2_goals})
match[:team_1_scorers].each do |scorer|
if Player.exists?(team: tf1.team, last_name: scorer)
Goal.create(team_score: ts1, player: Player.find_by(last_name: scorer))
else
new_player = Player.create(team: tf1.team, last_name: scorer)
Goal.create(team_score: ts1, player: new_player)
end
end
match[:team_2_scorers].each do |scorer_2|
if Player.exists?(team: tf2.team, last_name: scorer_2)
Goal.create(team_score: ts2, player: Player.find_by(last_name: scorer_2))
else
new_player = Player.create(team: tf2.team, last_name: scorer_2)
Goal.create(team_score: ts2, player: new_player)
end
end
end
It looks like you are using braces when you meant to use brackets to access the hash. Below is one of the issues, but the same issue is in ts2.
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match{:team_1_goals})
should be match[:team_1_goals]
ts1 = TeamScore.create(team_fixture: tf1, total_goals: match[:team_1_goals])
It may be because you have scheduled_matches_1 at the top and scheduled_matches.each do... further down.
But the real issue here is that your variable names match the data content, rather than being used to hold the content. If a new team joins your league, you have to change the code. Next week, you are going to have to change the hard-coded date value. Your scheduled_matches_1 data structure includes the active record objects returned by the first set of Team.findByName() calls. It would be easier to fetch these objects from the database inside your loops, and just hold the team name as a string in the hash.
There is some duplication too. Consider that each fixture has a home team and an away team. Each team has a name, and an array (possibly empty) of the players who scored. We don't need the number of goals; we can just count the number of players in the 'scorers' array. The other attributes, like the location and season belong to the fixture, not the team. So your hash might be better as
{
"fixtures": [
{
"home": {
"name": "Cavalry",
"scorers": [
"Minaev"
]
},
"away": {
"name": "Coalition",
"scorers": [
"Kovalev",
"Kovalev",
"Kovalev",
"Thomas",
"Thomas",
"Grivachev"
]
},
"venue": "Evropa",
"season": "s28"
}
]
}
because then you can create a reusable method to process each team. And maybe create a new method that returns the player (which it either finds or creates) which can be called by the loop that adds the goals.
Also, as it stands, I'm not sure the code can handle 'own goals', either. Perhaps something for a future iteration :)

can we delete element in list based on certain condition

I have a Python list:
test_list = ['LeBron James', 'and', 'Nina Mata', 'Dan Brown', 'Derrick Barnes', 'and',
'Gordon C. James', 'J. Kenji López-Alt', 'and', 'Gianna Ruggiero', ]
I want output like this:
final_list = ['LeBron James and Nina Mata', 'Dan Brown', 'Derrick Barnes and
Gordon C. James', 'J. Kenji López-Alt and Gianna Ruggiero']
In short, I want one item before 'and' one item after 'and' to be combined. On the other hand, names coming without 'and' should not be combined and left as it is. How can we do this in Python?
Here's a solution perhaps not too elegant but simple and functional: join all words with a glue symbol that does not happen in any of them (e.g., "~"), replace the resulting "~and~"s with " and "s, and split by the glue symbol again:
"~".join(test_list).replace("~and~", " and ").split("~")
#['LeBron James and Nina Mata', 'Dan Brown',
# 'Derrick Barnes and Gordon C. James',
# 'J. Kenji López-Alt and Gianna Ruggiero']
This should work for groups with more than one "and," too.

How can I get list values that meet specific conditions?

I'm an introductory member of Python.
I are implementing code to organize data with Python.
I have to extract a value that meets only certain conditions out of the numerous lists.
It seems very simple, but it feels too difficult for me.
First, let me explain with the simplest example
solutions
Out[73]:
array([[ 2.31350622e-04, -1.42539948e-02, -7.17361833e-02,
2.17545418e-01, -3.38251827e-01, 1.88254191e-01],
[ 4.23523963e-82, -9.48255372e-81, 5.22018863e-80,
-1.11271010e-79, 1.03507672e-79, -3.55573390e-80],
[ 2.31350597e-04, -1.42539951e-02, -7.17361800e-02,
2.17545409e-01, -3.38251817e-01, 1.88254187e-01],
[ 2.58309722e-02, -6.21550000e-01, 3.41867505e+00,
-7.53828444e+00, 7.09091365e+00, -2.39409614e+00],
[ 2.31350606e-04, -1.42539950e-02, -7.17361809e-02,
2.17545411e-01, -3.38251820e-01, 1.88254188e-01],
[ 1.14525725e-02, -3.25174709e-01, 2.11632584e+00,
-5.16113713e+00, 5.12508331e+00, -1.78380602e+00],
[ 9.75839726e-03, -3.08729919e-01, 2.26983591e+00,
-6.16462170e+00, 6.76409438e+00, -2.55992476e+00],
[ 1.13190092e-03, -6.72042220e-02, 7.10413638e-01,
-2.39952623e+00, 2.94849402e+00, -1.18046338e+00],
[ 5.24406689e-03, -1.86240596e-01, 1.36500589e+00,
-3.61106144e+00, 3.75606312e+00, -1.34699295e+00]])
coeff
Out[74]:
array([[ 1.03177808e-04, -6.35700011e-03, -3.19929208e-02,
9.70209594e-02, -1.50853634e-01, 8.39576506e-02,
4.45980248e-01],
[ 5.13911499e-83, -1.15062991e-81, 6.33426960e-81,
-1.35018220e-80, 1.25598048e-80, -4.31459067e-81,
1.21341776e-01],
[ 1.03177797e-04, -6.35700027e-03, -3.19929194e-02,
9.70209556e-02, -1.50853630e-01, 8.39576490e-02,
4.45980249e-01],
[ 4.26209161e-03, -1.02555298e-01, 5.64078896e-01,
-1.24381145e+00, 1.16999559e+00, -3.95024121e-01,
1.64999272e-01],
[ 1.03177801e-04, -6.35700023e-03, -3.19929198e-02,
9.70209566e-02, -1.50853631e-01, 8.39576495e-02,
4.45980248e-01],
[ 2.27512838e-03, -6.45980810e-02, 4.20421959e-01,
-1.02529362e+00, 1.01813129e+00, -3.54364724e-01,
1.98656535e-01],
[ 1.42058482e-03, -4.49435521e-02, 3.30432790e-01,
-8.97418681e-01, 9.84687293e-01, -3.72662657e-01,
1.45575629e-01],
[ 2.46722650e-04, -1.46486353e-02, 1.54850246e-01,
-5.23029411e-01, 6.42688990e-01, -2.57307904e-01,
2.17971950e-01],
[ 1.30617191e-03, -4.63880878e-02, 3.39990392e-01,
-8.99429225e-01, 9.35545685e-01, -3.35503798e-01,
2.49076135e-01]])
In a matrix defined as 'numpy', called 'solutions', each row represents 'solutions[0]','solutions[1]', 'solutions[i]'... In addition, the 'coeff' is also defined as 'numpy', and the 'coeff[0]','coeff[1]','coeff[i]'... is matched to 'solutions[0]','solutions[1]','solutions[i]'...
What I want at this time is to find specific 'solution[i]' and 'coeff[i]' where all elements of solutions[i] are less than 10^-10 and all elements of coeff[i] are greater than 10^-3.
I wonder if there is an appropriate code to extract a list array in a situation that meets more than one condition. I'm a Python initiator, so please excuse me.
This can be accomplished using advanced indexing:
solution_valid = np.all(solutions < 10e-10, axis=1)
coeff_valid = np.all(coeff > 1e-3, axis=1)
both_valid = coeff_valid & solution_valid
valid_solutions = solutions[both_valid]
valid_coeffs = coeff[both_valid]
but perhaps you mean that the absolute value should be greater or below a certain threshold?
solution_valid = np.all(np.abs(solutions) < 10e-10, axis=1)
coeff_valid = np.all(np.abs(coeff) > 1e-3, axis=1)
both_valid = coeff_valid & solution_valid
valid_solutions = solutions[both_valid]
valid_coeffs = coeff[both_valid]

Creating an array in Ruby

I am trying to create an array in Ruby. When my function is called to print the array, it seems that the array is undefined. I am wondering if my syntax is off.
Can someone please tell me if this is the correct way to create and instantiate an array in one line, or if the problem is somewhere else in my code?
Below is my Ruby code:
class Game
words = Array["hat", "cat", "ate", "run", "eye", "soup", "date",
"bake", "wake", "grape", "apple", "pride", "drive",
"tacos", "linux", "orange", "purple", "volume",
"liquid", "palace", "molasses", "diamond", "sausage",
"america", "england"]
# starts the game state to play
def start_x
# game logic for begin
puts(words)
end
# if users wins
def win
puts("congratulations! you win!")
end
# if user loses
def death
puts("sorry! you die!")
end
end
You either need to constantize words into WORDS or you need to make those values available through a getter method or an instance variable. Here are some examples:
Constantize, making the array available to any caller:
class Game
WORDS = ['hat', 'cat', 'ate', 'run', 'eye', 'soup', 'date',
'bake', 'wake', 'grape', 'apple', 'pride', 'drive',
'tacos', 'linux', 'orange', 'purple', 'volume',
'liquid', 'palace', 'molasses', 'diamond', 'sausage',
'america', 'england']
def start_x
puts(WORDS)
end
end
And then it works:
⇒ Game.new.start_x
hat
cat
ate
run
eye
soup
date
bake
wake
grape
apple
pride
drive
tacos
linux
orange
purple
volume
liquid
palace
molasses
diamond
sausage
america
england
Or with a getter method:
class Game
def words
#words ||= ['hat', 'cat', 'ate', 'run', 'eye', 'soup', 'date',
'bake', 'wake', 'grape', 'apple', 'pride', 'drive',
'tacos', 'linux', 'orange', 'purple', 'volume',
'liquid', 'palace', 'molasses', 'diamond', 'sausage',
'america', 'england']
end
def start_x
puts(words)
end
end
Or with an instance variable:
class Game
def initialize
#words = ['hat', 'cat', 'ate', 'run', 'eye', 'soup', 'date',
'bake', 'wake', 'grape', 'apple', 'pride', 'drive',
'tacos', 'linux', 'orange', 'purple', 'volume',
'liquid', 'palace', 'molasses', 'diamond', 'sausage',
'america', 'england']
end
def start_x
puts(#words)
end
end
Or combine with an attribute reader:
class Game
attr_reader :words
def initialize
#words = ['hat', 'cat', 'ate', 'run', 'eye', 'soup', 'date',
'bake', 'wake', 'grape', 'apple', 'pride', 'drive',
'tacos', 'linux', 'orange', 'purple', 'volume',
'liquid', 'palace', 'molasses', 'diamond', 'sausage',
'america', 'england']
end
def start_x
puts(words)
end
end
All work the same way and will be used in different circumstances.
Your code doesn't work, because words is a local variable declared outside the methods.
You probably want to have an instance variable here. And it's usually a good idea to separate the game code from the data. So instead of hard-coding the words into the Game class, you pass the data upon initialization:
class Game
def initialize(words)
#words = words
end
def start_x
puts #words
end
# ...
end
To call it:
words = %w[
hat cat ate run eye soup date bake wake grape apple pride drive tacos linux
orange purple volume liquid palace molasses diamond sausage america england
]
game = Game.new(words)
game.start_x
From here on, you could easily extract the data into a words.txt file:
hat
cat
ate
...
sausage
america
england
And load the data via:
words = File.readlines('words.txt' chomp: true)
game = Game.new(words)
game.start_x
This allows you to launch your game with different sets of words without having to modify your code.
I guess this would help you.
class Game
attr_reader :words
def initialize
#words = %w[hat cat ate run eye soup date
bake wake grape apple pride drive
tacos linux orange purple volume
liquid palace molasses diamond sausage
america england]
end
# if users wins
def win
puts("congratulations! you win!")
end
# if user loses
def death
puts("sorry! you die!")
end
end
You can access the words like Game.new.words

Ruby: Extract elements from deeply nested JSON structure based on criteria

Want to extract every marketID from every market that has a marketName == 'Moneyline'. Tried a few combinations of .maps, .rejects, and/or .selects but can't narrow it down as the complicated structure is confusing me.
There are many markets in events, and there are many events as well. A sample of the structure (tried to edit it for brevity):
{"currencyCode"=>"GBP",
"eventTypes"=>[
{"eventTypeId"=>6423,
"eventNodes"=>[
{"eventId"=>28017227,
"event"=>
{"eventName"=>"Philadelphia # Seattle"
},
"marketNodes"=>[
{"marketId"=>"1.128274650",
"description"=>
{"marketName"=>"Moneyline"}
},
{"marketId"=>"1.128274625",
"description"=>
{"marketName"=>"Winning Margin"}
}}}]},
{"eventId"=>28018251,
"event"=>
{"eventName"=>"Arkansas # Mississippi State"
},
"marketNodes"=>[
{"marketId"=>"1.128299882",
"description"=>
{"marketName"=>"Under/Over 60.5pts"}
},
{"marketId"=>"1.128299881",
"description"=>
{"marketName"=>"Moneyline"}
}}}]},
{"eventId"=> etc....
Tried all kinds of things, for example,
markets = json["eventTypes"].first["eventNodes"].map {|e| e["marketNodes"].map { |e| e["marketId"] } if (e["marketNodes"].map {|e| e["marketName"] == 'Moneyline'})}
markets.flatten
# => yields every marketId not every marketId with marketName of 'Moneyline'
Getting a simple array with every marketId from Moneyline markets with no other information is sufficient. Using Rails methods is fine too if preferred.
Sorry if my editing messed up the syntax. Here's the source. It looks like this only with => instead of : after parsing the JSON.
Thank you!
I love nested maps and selects :D
require 'json'
hash = JSON.parse(File.read('data.json'))
moneyline_market_ids = hash["eventTypes"].map{|type|
type["eventNodes"].map{|node|
node["marketNodes"].select{|market|
market["description"]["marketName"] == 'Moneyline'
}.map{|market| market["marketId"]}
}
}.flatten
puts moneyline_market_ids.join(', ')
#=> 1.128255531, 1.128272164, 1.128255516, 1.128272159, 1.128278718, 1.128272176, 1.128272174, 1.128272169, 1.128272148, 1.128272146, 1.128255464, 1.128255448, 1.128272157, 1.128272155, 1.128255499, 1.128272153, 1.128255484, 1.128272150, 1.128255748, 1.128272185, 1.128278720, 1.128272183, 1.128272178, 1.128255729, 1.128360712, 1.128255371, 1.128255433, 1.128255418, 1.128255403, 1.128255387
Just for fun, here's another possible answer, this time with regexen. It is shorter but might break depending on your input data. It reads the json data directly as String :
json = File.read('data.json')
market_ids = json.scan(/(?<="marketId":")[\d\.]+/)
market_names = json.scan(/(?<="marketName":")[^"]+/)
moneyline_market_ids = market_ids.zip(market_names).select{|id,name| name=="Moneyline"}.map{|id,_| id}
puts moneyline_market_ids.join(', ')
#=> 1.128255531, 1.128272164, 1.128255516, 1.128272159, 1.128278718, 1.128272176, 1.128272174, 1.128272169, 1.128272148, 1.128272146, 1.128255464, 1.128255448, 1.128272157, 1.128272155, 1.128255499, 1.128272153, 1.128255484, 1.128272150, 1.128255748, 1.128272185, 1.128278720, 1.128272183, 1.128272178, 1.128255729, 1.128360712, 1.128255371, 1.128255433, 1.128255418, 1.128255403, 1.128255387
It outputs the same result as the other answer.

Resources