people = {
"fruits" => {
kiwi: ["john","james","diana"],
apple: ["hibaq","nura","nadia"],
strawberry: ["hana", "valerie","india"] },
"sports" => {
rugby: ["john","james","diana"],
football: ["hibaq","nura","nadia"],
tennis: ["hana", "valerie","india"]
}
}
puts 'Enter what category to search'
category = gets.chomp
puts 'Enter what value to search for'
value = gets.chomp
people.select { |person| person[category] == value }
.each { |person| puts person["name"] }
Hi, I am new to ruby and trying to understand hashes a bit more. I want to ask the user for a category e.g "fruits" and then print the array of names that like the fruit. I am unsure how to iterate through the nested hash to access the information. Any guidance would be greatly appreciated. Thank you
Hi, I am new to ruby and trying to understand hashes a bit more. I want to ask the user for a category e.g "fruits" and then print the array of names that like the fruit. I am unsure how to iterate through the nested hash to access the information. Any guidance would be greatly appreciated. Thank you
The following should work for you.
Please note that I changed the nested hash structure to use Strings instead of Symbols in the inner hashes. Because gets returns already a string that makes it easier to get the data by the key (string) that the user entered.
people = {
"fruits" => {
"kiwi" => ["john","james","diana"],
"apple" => ["hibaq","nura","nadia"],
"strawberry" => ["hana", "valerie","india"]
},
"sports" => {
"rugby" => ["john","james","diana"],
"football" => ["hibaq","nura","nadia"],
"tennis" => ["hana", "valerie","india"]
}
}
puts 'Enter what category to search'
category = gets.chomp # when entered "sports"
puts 'Enter what value to search for'
value = gets.chomp # when entered "rudby"
p people.dig(category, value)
#=> ["john", "james", "diana"]
See Hash#dig. Other options to get data out of a Hash might be Hash#[] or Hash#fetch.
Firstly, you would make life simpler for yourself by using a consistent format when writing your hash people. I suggest
people = {
fruits: {
kiwi: ["john","james","diana"],
apple: ["hibaq","nura","nadia"],
strawberry: ["hana", "valerie","india"] },
sports: {
rugby: ["john","james","diana"],
football: ["hibaq","nura","nadia"],
tennis: ["hana", "valerie","india"]
}
}
Notice that I have written fruits: { ... rather than 'fruits' => { ... to be consistent with, for example, kiwi: [ ....
With this change we can write the following helper method which can be used for both the outer hash and the inner hashes.
def obtain_response(keys, type)
loop do
puts "Enter what #{type} to search for"
k = gets.chomp.to_sym
break k if keys.include?(k)
puts "There is no such #{type} '#{k}'. Please try again"
end
end
We may then write
category = obtain_response(people.keys, 'category')
value = obtain_response(people[category].keys, 'value')
p people[category][value]
Here is an example session.
category = obtain_response(people.keys, 'category')
Computer User
-------- ----
Enter what category to search for
colours
There is no such category 'colours'. Please try again
Enter what category to search for
sports
Now
category
#=> :sports
Next
value = obtain_response(people[category].keys, 'value')
Computer User
-------- ----
Enter what value to search for
darts
There is no such value 'darts'. Please try again
Enter what value to search for
football
Now
value
#=> :football
We may now display the desired array.
p people[category][value]
#=> ["hibaq", "nura", "nadia"]
One may of course employ more elaborate prompts, such as
Enter the category to search for ("fruits" or "sports")
Related
I am trying to fetch some data from my neo4j database and show in a list for auto suggestion in reactjs application. I have following codes to fetch the data.
let result = null;
try {
result = await session.run(
'MATCH (n:Person) RETURN properties(n)',
)} finally {
await session.close()
}
await driver.close()
Here the Person nodes have different properties, i.e. all the Person nodes do not have same properties. some have editor name, others have author name. What i want to do is fetching only values without keys and assigning them in an array. here
'MATCH (n:Person) RETURN properties(n)'
returns
{
"myName": "myname 1",
"hisName": "myname 2"
}
{
"herName": "myname 3",
"theirName": "myname 4"
}
And 'MATCH (n:Person) RETURN keys(n)' returns
["myName"]
["hisName"]
["herName"]
["theirName"]
But i want to fetch only values [myname 1, myname 2, myname 3, myname 4]
Could you please tell me how to fetch only values ?
Also how to keep those values in an array ?
This is how to get all values for the key myName in Person class.
Check if the node has this property using EXISTS
Put the values in an array using "COLLECT".
MATCH (n:Person)
WHERE EXISTS(n.myName)
RETURN collect(distinct n.myName)
Sample result:
["Zhen", "Praveena", "Michael", "Arya", "Karin", "Adam", "John", "mary", "jack", "david", "tom"]
This will work.
MATCH(n:Person)
RETURN apoc.coll.flatten(COLLECT(EXTRACT(key IN keys(n) | n[key])))
p.s. Sorry, EXTRACT() has been deprecated. Below is better.
MATCH(n:Shima)
RETURN apoc.coll.flatten(COLLECT([key IN keys(n) | n[key]]))
Newbie here and this is a project I'm building to learn. I'm going around in circles so forgive my ignorance please. I'm now not even sure that what I want to do is possible. I also understand that there are probably better ways to achieve my ultimate goal but this is what I have.
I have an array that includes some user input.
"participants": [ {
"name": "Cristina",
"email": "cristina#gmail",
"yourPerson": "Richard",
"spouseEmail": "Richard#gmail" } ] }
I want to pull the "name" and "youPerson" values and use them as a key:value pair. So name would be the key and yourPerson would be the value.
I thought I could use a forEach but no matter what I do I either get an undefined array or I copy the entire array, not just those two fields.
here is my code at the moment:
participantArray = [];
namePlusSpouseArray = [];
submitParticipant() {
this.participantArray.push(this.participantForm.value);
console.log(this.participantArray)
this.createNamePlusSpouseArray();
}
createNamePlusSpouseArray() {
this.participantArray.forEach(name => {
this.namePlusSpouseArray.push(this.participantArray[name]);
console.log(this.namePlusSpouseArray)
});
}
Not sure if you want a result array of key value pairs, or you want 1 object/map/dictionary/lookup of name -> youPerson
Assuming you want an array containing key value pairs, you can use map
this.namePlusSpouseArray = this.participantArray.map(participant => ({
[participant.name]: participant.youPerson
});
If you want a lookup of name -> youPerson, the "namePlusSpouseArray" shouldn´t be an array but instead just an object
namePlusSpouseLookup = {};
this.participantArray.forEach(participant => {
this.namePlusSpouseLookup[participant.name] = participant.youPerson;
});
The simplest solution is:
const participantArray = {
"participants": [ { "name": "Cristina", "email": "cristina#gmail", "yourPerson": "Richard", "spouseEmail": "Richard#gmail" } ] };
const createPair = participants => {
return participants.map(participant =>
({ [participant.name]: participant.yourPerson}))
}
console.log(createPair(participantArray.participants));
My first post here. I tried to search for an answer, but no luck, so here we go
Generally I cannot share with you with the exact code I'm working on :(
so here's the example one:
$collection = collect(['country' => 'Germany', 'city' => 'Berlin', 'month' => 'April']);
dd($collection);
//"country" => "Germany"
//"city" => "Berlin"
//"month" => "April"
$array1 = ['France', 'Paris', 'May'];
$array2 = ['Spain', 'Madrid', 'June'];
My question is - how to "add" those arrays (minding array1 and array2 order) so I end up with something like this?
dd($newCollection);
//output:
//"country" => ["Germany", "France", "Spain"]
//"city" => ["Berlin", "Paris", "Madrid"]
//"month" => ["April", "May", "June"]
OR
If there's a way to get all records from database and make one of the rows a key and a selection of them as values
Example
$users = User::get();
//this table has columns "full_name", "e-mail", "job", "birth_date", "city" and "password"
$collection = <<???>> //make column "full_name" as key and columns "e-mail", "job", "password" as values
dd($collection);
//output:
//"John Doe" => ["johndoe#mail.com", "Janitor", "topsecret"]
//"Jane Doe" => ["janedoe#mail.com", "teacher", "sercretpassword"]
Lifetime gratitude in advance for an answer... I've read Laravel's documentation many times and could not find a solution
I've got this
The solution for me looks like this:
$users = User::get();
//this table has columns "id", "full_name", "e-mail", "job", "birth_date", "city" and "password"
//I don't want to use all columns here
foreach($users as $user=>$value){
$full_name = $value->full_name;
$e-mail = $value->e-mail;
$job = $value->job;
$password -> $value->password;
$endresult[] = [$full_name, $e-mail, $job, $password];
}
$collection = collect($users->keyBy('id')->pluck('id'))->combine($endresult);
dd($collection);
//output:
// 1 => ["John Doe", "johndoe#mail.com", "Janitor", "topsecret"]
// 2 => ["Jane Doe", "janedoe#mail.com", "teacher", "sercretpassword"]
It looks terrible, but works like a charm. I needed to format this like so because in my project there are many foreign keys and I need to pagify my results, so to make it the easiest way possible I need to combine all values to one key (just like a row in csv) rather than call for every value in view
thank you for your support
You've technically asked two questions here. One where you merge a set of values into a key-value collection, and another where you simply limit the values from a set of key-value collections and key by the ID.
Given that you're really looking for an answer to the second question, by way of your answer, here's a cleaner way of doing it:
User::select('id', 'full_name', 'email', 'job', 'password')
->get()
->keyBy('id')
->map(function($user) {
return collect($user)->except('id');
});
My code stays in the second for forever, testing the same category every step and decrementing every time.
I have two arrays, one of them is called categoriesToUpdate and is a list of category ids (string values) for categories that I have to update, and the other is called categories, containing all the actual category data I'm working with.
I have to test if the id value for a category that I have to update is the same as the database and if it is, decrement the attribute position of its object and update the database. But it is infinitely decrementing the bank.
let newCategory;
let name;
let position;
for(let id of categoriesToUpdate) {
for(let cat of categories) {
if(id === cat.id) {
position = cat.category.category.lastPosition - 1;
name = cat.category.category.categoryName;
newCategory = {
category: {
categoryName: name,
lastPosition: position,
}
}
cRef.child(id).update(newCategory);
}
}
}
Examples of the two arrays:
categoriesToUpdate = ['-lGz4j77...', '-uEbKO3...', ...]
and
categories = [
{
category: {
category: {
categoryName: "name",
lastPosition: "number",
}
},
id: "category id";
},
{
...
}
]
it is difficult to explain how I get the arrays, but basically, categoriesToUpdate is an array of ids that I add to my logic, I have to do update in each of these categoriesand categories is an array that has all categories of the database, comes from Firebase.
let id of categoriesToUpdate. I'm assuming categoriesToUpdate is an array of Category objects. So id is actually a Category object. To compare it should be id.id === cat.id.
Also you can try filter instead of a second loop.
Something like
var matched = categories.filter(c => c.id === id.id)[0];
Then compare matched. Nested loops are hard to read, imo.
I have this big array that I need to break down and only display specific elements within it that match a criteria.
My array looks like this.
[
{
:id => 9789,
:name => "amazing location",
:priority => 1,
:address_id => 12697,
:disabled => false
},
{
:id => 9790,
:name => "better location",
:priority => 1,
:address_id => 12698,
:disabled => false
},
{
:id => 9791,
:name => "ok location",
:priority => 1,
:address_id => 12699,
:disabled => true
}
]
What I need is to only display the elements within this array that have disabled set to true.
However when I try this, I get the error stating no implicit conversion of Symbol into Integer
array.map do |settings, value|
p hash[:disabled][:true]
end
I'm wondering if there is another way, or if there is a way to do this. If anyone could take a look, I would greatly appreciate it.
By providing two arguments to #map on an array, you're actually getting the first hash and then nil. When in reality you just want to loop for each and select those where disabled is true. You can do that instead with Array#select which will filter all elements of the array where the block returns a truthy value:
print array.select { |hash| hash[:disabled] }
=> [{:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}]
You can try this with a short each or select.
a.each { |k,_v| puts k if k[:disabled] == true }
=> {:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}
This iterates over each element (hash) inside the array you have and checks if the value of the key disabled on each value is true, and puts the key, just for example, you can set it as you want to do.
Or shorter:
puts a.select { |k,_v| k[:disabled] }
=> {:id=>9791, :name=>"ok location", :priority=>1, :address_id=>12699, :disabled=>true}
Your error shows up when you are treating an array or string as a Hash.
In PHP, array keys can be either numbers or strings, whereas in Ruby associative arrays are a separate data type, called a hash.
Here’s a cheatsheet for various foreach variants, translated into idiomatic Ruby:
Looping over a numeric array (PHP) :
<?php
$items = array( 'orange', 'pear', 'banana' );
# without indexes
foreach ( $items as $item ) {
echo $item;
}
# with indexes
foreach ( $items as $i => $item ) {
echo $i, $item;
}
Looping over an array (Ruby) :
items = ['orange', 'pear', 'banana']
# without indexes
items.each do |item|
puts item
end
# with indexes
items.each_with_index do |item, i|
puts i, item
end
Looping over an associative array (PHP) :
<?php
$continents = array(
'africa' => 'Africa',
'europe' => 'Europe',
'north-america' => 'North America'
);
# without keys
foreach ( $continents as $continent ) {
echo $continent;
}
# with keys
foreach ( $continents as $slug => $title ) {
echo $slug, $title;
}
Looping over a hash (Ruby):
continents = {
'africa' => 'Africa',
'europe' => 'Europe',
'north-america' => 'North America'
}
# without keys
continents.each_value do |continent|
puts continent
end
# with keys
continents.each do |slug, title|
puts slug, title
end
In Ruby 1.9 hashes were improved so that they preserved their internal order. In Ruby 1.8, the order in which you inserted items into a hash would have no correlation to the order in which they were stored, and when you iterated over a hash, the results could appear totally random. Now hashes preserve the order of insertion, which is clearly useful when you are using them for keyword arguments in method definitions. (thanks steenslag for correcting me on this)