First array element that matches an element in another array - arrays

I'm trying to return the first element in the given array that matches an element in a preset array. I have this:
def find_the_cheese(a)
cheese_types = ["cheddar", "gouda", "camembert"]
a.collect{|c| cheese_types.include?(c)}.include?(true)
end
But it returns true rather than the c value from the enclosed brackets. How can I return the matching element?

Following code will returning elements from food which include in cheese_types
def find_the_cheese(food)
cheese_types = ["cheddar", "gouda", "camembert"]
food & cheese_types
end

The Array class includes the Enumerable module. Enumerable#find does just that:
def find_the_cheese(foods)
cheeses = ["cheddar", "gouda", "camembert"]
foods.find { |food| cheeses.include?(food) }
end

CheeseTypes = ["cheddar", "gouda", "camembert"]
def find_the_cheese(a)
(a & CheeseTypes).first
end

Related

Return object after performing intersection of two arrays based on attribute

I have two arrays, both filled with objects that have numerous attributes. Both arrays are holding the same object types. I want to find where objects match based on their attribute id
Object example:
#<Link:0x00007fac5eb6afc8 #id = 2002001, #length=40, #area='mars' ...>
Example arrays filled with objects:
array_links = [<Link:0x00007fac5eb6afc8>, <Link:0x00007fdf5eb7afc2>, <Link:0x000081dag6zb7agg8>... ]
selected_links = [<Link:0x00007fad8ob6gbh5>, <Link:0x00007fdg7hh4tif4>, <Link:0x000081dag7ij5bhh9>... ]
If these were strings of the object IDs and there was a match, I could use:
intersection = array_links & selected_links
However I want to do this based on their attribute and return a matching object itself.
Something like:
intersection = array_links.select(&:id) & selected_links.select(&:id)
But of course, not that, as that doesn't work, any ideas? :)
you can:
1 :
override the eql?(other) method then the array intersection will work
class Link < ApplicationRecord
def eql?(other)
self.class == other.class && self.id == other&.id # classes comparing class is a guard here
end
# you should always update the hash if you are overriding the eql?() https://stackoverflow.com/a/54961965/5872935
def hash
self.id.hash
end
end
2:
use array.select:
array_links.flat_map {|i| selected_links.select {|k| k.user_id == i.user_id }}
If they are the same object in memory, ie array_links = [<Link:0x123] and selected_links = [<Link:0x123>], then your solution of:
intersection = array_links & selected_links
Should work.
If they are not, you could loop over you array_links and select those which are in selected_links:
intersection = array_links.select do |link|
link.id.in? selected_links.map(&:id)
end
The result will be the same if you loop over selected_links and select those in array_links.
Depending on your resources and the size of these arrays, you could memoize selected_links.map(&:id) to prevent this from being re-built on each iteration.

How to check for the presence of an element in an array if this element is entered by the user? (Python)

I have an array and element in it. Then I'm requiring user input and storing it in a variable.
root = []
#adding class for file
class my_file:
def __init__(self, file_name, content):
self.file_name = file_name
self.content = content
#creating object
hello = my_file("hello", "some text")
#adding object to root array
root.append(hello)
usrInput = input("Enter element")
The question is: how to check for the presence of an element in the root array if the element itself is contained in a variable? I tried the following:
if usrInput in root:
print(root[root.index(usrInput)].content)
But if usrInput in root returns false. I think this is because usrInput is being treated as the intended element of the array and not as a variable. Is there any way to fix this error?
I made the whole array iterate over and each element was compared with user input. As soon as a match was found, the access operator and the property name of the object were added to the index of the matched element
i = 0
isFound = False
while isFound != True:
if usrInput == root[i].file_name:
print(root[i].content)
isFound = True
else:
i += 1

Ruby variable regular expression in Array Select

I'm trying to exclude elements from an array of strings using array.select. I have this method:
def filter_out_other_bad_vals(array_of_strs, things_i_want)
array_of_strs = array_of_strs.select { |line| /"#{things_i_want}"/.match(line) }
end
I want to pass a string as a variable things_i_want. But this does not return any matches:
array = ["want_this", "do_not_want", "do_not_want","want_this", "want_this"]
pattern = 'want_this'
array = filter_out_other_bad_vals(array, pattern)
This returns an empty array. But if I hardcode the value in the match expression, I get what I want.
def filter_out_other_bad_vals(array_of_strs, things_i_want)
array_of_strs = array_of_strs.select { |line| /want_this/.match(line) }
end
How do I put a variable in the regex? What am I doing wrong?
I could just traverse the array, check each item, and then save the value in another array, but that's not very ruby-like, is it?
You include quotes in regex definition:
/"#{things_i_want}"/
remove them and it should work:
/#{things_i_want}/
EDIT:
By the way, you don't have to use regex for exact matching, you can use equality check (==) or #include? depending if you need a string to be equal to thing you want or just include it:
> array = ["want_this", "do_not_want", "do_not_want","want_this", "want_this"]
> array.select{|line| line == 'want_this'}
# => ["want_this", "want_this", "want_this"]
> array.select{|line| line.include? 'want_this'}
# => ["want_this", "want_this", "want_this"]

How to check for Hash value in an array?

Heres my set up
project_JSON = JSON.parse
teamList = Array.new
project = Hash.new()
project["Assignee Name"] = issue["fields"]["assignee"]["displayName"]
project["Amount of Issues"] = 0
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
project_JSON.each do |x|
project["Amount of Issues"] += 1
teamList.push(project)
end
Im having trouble with this line.
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
It always returns true even after the .push. I want to make an array of my team members and list how many times their name appears in my JSON. What am I doing wrong and how do I dynamically refer to a hash value in an if statement(thats where I think its wrong because if I am saying .include?(issue["fields"]["assignee"]["displayName"]) wrong then its nil and the if statement will always be true)?
In your code teamList is an empty array, so it does not include? anything, it will always return false. Now because you are using ! operator it always returns true.
EDIT
If understood it right, you have to loop through the array checking each element for the value specified.
Below is a way to do it, mind you I replaced keys for symbols as it's a good practice in Ruby:
issue = {
:fields => {
:assignee => {
:displayName => 'tiago'
}
}
}
teamList = Array.new
def teamList.has_assignee?(assignee)
self.each do |e|
return e[:assignee] == assignee
end
false
end
project = Hash.new
project[:assigneeName] = issue[:fields][:assignee][:displayName]
project[:amountOfIssues] = 0
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
puts teamList.inspect # only one object here
As Sergio pointed out you could use .detect
def teamList.has_assignee?(assignee)
self.detect { |e| e[:assigneeName] == assignee }
end

check if array includes an instance with a certain value for an instance variable Ruby

So if a have this code:
class A
def initialize(type)
#type = type
end
end
instance = A.new(2)
another_instance = A.new(1)
array = [instance, another_instance]
is there a way to check if array includes an instance of A where #type is equal to a certain value? say, 2? like the include? method but where instead of checking for an instance of a certain class, it also checks the instance variables of that class?
I would recommend using anattr_reader for this one unless you plan on modifying the type somewhere after (in that case use attr_accessor which is both a writer and reader)
class A
attr_reader :type
def initialize(type)
#type = type
end
end
instance = A.new(2)
another_instance = A.new(1)
array = [instance, another_instance]
array.select do |item|
item.type == 2
end
=>[#<A:0x00000000dc3ea8 #type=2>]
Here I am iterating through an array of instances of A and selecting only the ones that meet the condition item.type == 2
You can just refer to the instance variable.
> array.any? { |item| item.is_a?(A) }
=> true
> array.any? { |item| item.instance_variable_get(:#type) == 1 }
=> true
> array.select { |item| item.instance_variable_get(:#type) == 1 }
=> [#<A:0x007fba7a12c6b8 #type=1>]
Or, use attr_accessor in your class, to make it way easier
class A
attr_accessor :type
def initialize(type)
#type = type
end
end
then you can do something = A.new(5); something.type

Resources