How can i access values of aaa, xxx, yyy & zzz from into separate variables, as it does seems mix of maps/tuple.
{{: xxx, %{yyy: 'something', zzz: 'test'}, {aaa: 'best'}}}
Sorry guys for troubling you, i got that working as
iex(1)> {a, b, c} = {: xxx, %{yyy: 'something', zzz: 'test'}, {aaa: 'best'}}
{: xxx, %{yyy: 'something', zzz: 'test'}, {aaa: 'test'}}
iex(2)> a
:xxx
iex(3)> b
%{yyy: 'something', zzz: 'test'}
iex(4)> b[:zzz]
'test'
thanks anyways to all.
You can even pattern-match on map keys:
iex(1)> {a, %{zzz: b}, %{aaa: c}} = {:xxx, %{yyy: "something", zzz: "test"}, %{aaa: "best"}}
{:xxx, %{yyy: "something", zzz: "test"}, %{aaa: "best"}}
iex(2)> a
:xxx
iex(3)> b
"test"
iex(4)> c
"best"
See http://elixir-lang.org/getting_started/7.html
Btw, in Elixir, single- and doublequotes have different meaning (charlist vs. binary). If you don't really need singlequotes (charlist), use doublequotes everywhere - binary is the default string format in Elixir (see String docs)
Related
I have a YAML document that contains an array. I would like to conditionally add properties to the elements of that array using yq version 4 from mikefarah.
Here is a sample YAML document.
name: "My Pets"
pets:
- name: "cat"
age: 8
- name: "dog"
age: 3
- name: "mouse"
age: 1
I would like to transform this into,
name: "My Pets"
pets:
- name: "cat"
age: 8
shots: cat.upToDate
- name: "dog"
age: 3
shots: dog.upToDate
- name: "mouse"
age: 1
shots: mouse.upToDate
where we add a shots property to each element of pets. The value of shots should be whatever the name value is, dot, upToDate.
I'm trying something like this,
yq eval '.pets[] | select(.name == "cat").shots = "cat.upToDate"' test.yaml
but that produces,
name: "cat"
age: 8
shots: cat.upToDate
name: "dog"
age: 3
name: "mouse"
age: 1
I need to preserve the entire original YAML document and just insert the shots property.
This is close but missing all of the other pets.
yq eval '.pets = (.pets[] | select(.name == "cat").shots = "cats.upToDate")' test.yaml
It produces,
name: "My Pets"
pets:
name: "cat"
age: 8
shots: cats.upToDate
I'm thinking maybe we could store the name of the pet in a variable and reference that later, but v4 is brand new to me today.
I would prefer to have a one-liner so that I don't have to filter on .name. This array has less than 10 elements so I could easily hard-code the name and call yq 10 times.
Any thoughts or suggestions? Many thanks, Weldon
Use |=, e.g. like so:
yq eval '.pets[] |= (.shots = (.name + ".upToDate"))' pets.yaml
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.
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
I have two arrays
b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
Currently I am using the union operator on these two arrays, like this: a | b. When combined, even though the names in each array are the "same" name (they're just using the shortened version of the name), it will duplicate my names.
My proposed solution to this is simply choose the first occurrence of first initial + last name as the name to perform the union on, however, I don't recall there being any methods in Ruby that can perform such an operation.
So the result of some_method(a | b) will return c which is just:
["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
I am wondering how I could go about achieving this?
b = ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
a = ["Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
r = /
\s # match a space
[[:alpha:]]+ # match > 0 alphabetic characters
\z # match end of string
/x # free-spacing regex definition mode
(b+a).uniq { |str| [str[0], str[r]] }
#=> ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas"]
This uses the form of the method Array#uniq that employs a block.
You may alternatively write (b|a).uniq { |str| [str[0], str[r]] }
The steps are as follows.
c = b+a
# => ["John Roberts", "William Koleva", "Lili Joe", "Victoria Jane", "Allen Thomas",
# "Jon Roberts", "Wil Koleva", "Lilian Joe", "Vic Jane", "Al Thomas"]
The first element of c passed to the block is
str = c.first
#=> "John Roberts"
so the block calculation is
[str[0], str[r]]
#=> ["J", " Roberts"]
The calculations are similar for all the other elements of c. The upshot is that
c.uniq { |str| [str[0], str[r]] }
is equivalent to selecting the first elements of c, when converted to [<first name initial>, <last name>], that match an element of the array d, where
d = [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"],
["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]].uniq
#=> [["J", "Roberts"], ["W", "Koleva"], ["L", "Joe"], ["V", "Jane"], ["A", "Thomas"]]
Pascal suggested that it would be better for uniq's block to return a string:
{ |str| "#{str[0]} #{str[r]}" }
(e.g., "J Roberts") which might instead be written
{ |str| str.sub(/(?<=.)\S+/,"") }
The inclusion of the space after the first initial is optional (e.g., "JRoberts" would also work).
Sure, just use Enumerable#uniq with a block:
c = (a | b).uniq do |full_name|
first_name, last_name = full_name.split(nil, 2)
[first_name[0], last_name]
end
Note: the first iteration of the code used the initials instead of abbreviated name.
Perhaps you can introduce the concept of a Name? It's a bit more code than just providing a block to uniq but it nicely encapsulates everything related.
class Name
def initialize(first, last)
#first, #last = first, last
end
def abbreviated
"#{#first[0]} #{#last}"
end
def eql?(other)
return false if !other.respond_to?(:abbreviated)
abbreviated == other.abbreviated
end
def hash
abbreviated.hash
end
def full
"#{#first} #{#last}"
end
end
a = Name.new('John', 'Roberts')
b = Name.new('Jon', 'Roberts')
c = Name.new('William', 'Koleva')
d = Name.new('Wil', 'Koleva')
x = [a, c]
y = [b, d]
p (y | x).map(&:full)
It's worth noting that abbreviated firstname does not really suffice to check equality of names.
Consider:
Jim Jackson
James Jackson
Janine Jackson
...
headers is an array that is populated from a file. When I print headers, I get:
headers = ["The Year", , , "The Make", "The Model"]
I'm trying to use headers.remove(' ') to get rid of those two cells that are just spaces. It will not run or compile with that syntax, and I cannot find what I am doing wrong. I have tested:
def list1 = ['j', 2, 3, 4]
list1.remove('j')
And it works just fine. I cannot figure out what I'm doing wrong.
Assuming that ["The Year", , , "The Make", "The Model"] is actually the toString representation of the list
groovy:000> ["The Year", , , "The Make", "The Model"]
ERROR org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed:
groovysh_parse: 1: unexpected token: , # line 1, column 14.
["The Year", , , "The Make", "The Model"]
^
groovy:000> ['"The Year"', '', '', '"The Make"', '"The Model"']
===> ["The Year", , , "The Make", "The Model"]
I think headers.remove(' ') isn't working because the elements aren't actually spaces, they're empty. I'm not sure why headers.remove('') wouldn't work, except that you'd need to use headers.removeAll('').
A better option would be to use something like headers.findAll { it.trim() != '' }.