Simple way to check for membership in a list? - swift2

For use in a closure (though I suppose it will be useful elsewhere as well), what is the cleanest way to check to see whether or not a given element is a member of a list (or any character is a member of a string)?
For example, to check whether or not the string "abcde" contains any of the characters in "aeiou", or whether the list ["bill", "sam" , "suzy"] contains any of the names in ["abe", "bill", "charlie"]?

1 ) Common chars in 2 words
You easily check the intersection of the common chars in 2 strings using the Set struct:
let set0 = Set("abcde".characters)
let set1 = Set("aeiou".characters)
let intersection = set0.intersect(set1) // {"e", "a"}
2) Common words in 2 lists
Similarly you can find the intersection of 2 arrays of strings:
let set0 : Set = ["bill", "sam", "suzy"]
let set1 : Set = ["abe", "bill", "charlie"]
let intersection = set0.intersect(set1) // {"bill"}
3) Back to Array
Please note that in both examples, the intersection constant is a Set. You can transform it into an Array writing:
let list = Array(intersection)
Hope this helps.
P.S. This code is for Swift 2.0
Update
More specifically if you want to find out whether an intersection exists you can simply write:
!intersection.isEmpty

Swift arrays have built in functions for this exact functionality.
I recommend checking out the official documentation for Collection Types from Apple for a starting point.
Here is an example that follows your question:
// With [Character]
let vowels: [Character] = ["a", "e", "i", "o", "u"]
let chars: [Character] = ["a", "b", "c", "d", "e"]
let resultVowels = vowels.filter { chars.contains($0) }
resultVowels.count // == 2
resultVowels.description // == "[a, e]"
// With [String]
let people = ["Bill", "Sam", "Suzy"]
let peeps = ["Abe", "Bill", "Charlie"]
let resultPeople = people.filter { peeps.contains($0) }
resultPeople.count // == 1
resultPeople.description // == "[Bill]"
The result will be the names (or numbers, characters, etc.) that are matching up. So you can not only get the count, but also the contents of the comparison in this procedure. So long as the types follow Equatable, this will work for you.
If you want to return a Boolean, just simply:
return filteredArray.count != 0
Now, if you want to compare say, a [Character] to a String then:
let vowels: [Character] = ["a", "e", "i", "o", "u"]
let someString = "abcde"
let result = vowels.filter { someString.characters.contains($0) }
result.count // == 2
result.description // == "[a, e]"
The String.characters property is a new feature brought in to Swift 2.
I hope I was able to assist you.

Related

How do I sort a randomized word in python for my hangman program (without it in alphabetical order and rather in its own order)?

In my hangman program, I am experiencing some difficulties in trying to organize the user's correctly guessed inputs (when they guess a letter correctly). For example, if the word was "frog", and the user guessed in the order "r", "o", "f", "g", the program should sort it (eventually) into "frog". When I do the .sort() function, it arranges it in alphabetical order (e.g. "fgor" for "frog"). Before using the .sort() method, I had no means of arranging it.
Here is a small piece of my code (pretending the word is "frog" which it isn't in my program):
word = "frog"
guess = input("Put in a letter") # with an iteration of a while loop
def hangman():
nothing = []
points = 0
while num_of_lives >= 1:
guess = input("Put in a letter: ")
for i in word1:
if guess in i:
print(guess, "is one of the letters")
points += 1
nothing += i
nothing2 = []
for y in nothing[:]:
nothing2[0:] += y[0:]
nothing2.sort()
print(nothing2)
You can define a custom sort method using this technique:
https://www.geeksforgeeks.org/python-list-sort/
# Python program to demonstrate sorting by user's
# choice
# function to return the second element of the
# two elements passed as the parameter
def sortSecond(val):
return val[1]
# list1 to demonstrate the use of sorting
# using using second key
list1 = [(1, 2), (3, 3), (1, 1)]
# sorts the array in ascending according to
# second element
list1.sort(key = sortSecond)
print(list1)
You just need to create a function that returns the letter's position in the original word. This can be used to yield the key for comparison. For that I would look at pythons' list.index

How do I check if a dictionary has a key in it in Julia?

Suppose I have a Dict object and a key value and I want to see if there's already an entry in the dictionary for that key? How do I do this?
There are a few ways to do this. Suppose this is your dictionary:
d = Dict(
"aardvark" => 1,
"bear" => 2,
"cat" => 3,
"dog" => 4,
)
If you have a key you can check for its presence using the haskey function:
julia> haskey(d, "cat")
true
julia> haskey(d, "zebra")
false
A slightly fancier way to check this is to check if the key is in the set of keys returned by calling keys(d):
julia> ks = keys(d)
Base.KeySet for a Dict{String,Int64} with 4 entries. Keys:
"aardvark"
"bear"
"cat"
"dog"
julia> "cat" in ks
true
julia> "zebra" in ks
false
Finally, it's fairly common that you want to get the value associated with a key if it is present in the dictionary. You can do that as a separate step by doing d[k] after checking that k is present in keys(d) but that involves an additional dictionary lookup. Instead, if there is some sentinel value that you know cannot be a value in your dictionary, such as nothing, then you can use the get function to look up the key with a default:
v = get(d, k, nothing)
if v !== nothing
# keys(d) contains k
end
If you know nothing about the kinds of values that d can map keys to, this is not a safe option since it could be the case that the pair k => nothing is present in d.
Ok not exactly an answer but still relevant to the discussion, something I learnt recently about julia dictionary accessor method that has made my life a lot easier.
val = get(dict, "key", nothing)
also has a version that creates the dictionary entry and sets it to the default value if it does not already exist
val = get!(dict, "key", nothing)
which does away with writing a lot of blocks like this
if !haskey(dict, "key")
dict["key"] = nothing
end
val = dict["key"]
so now instead of littering your code with key checks and dictionary value initialization blocks you can use get! instead.

how do i combine variables?

im making a program and i need to combine a lot of variables, most of them strings but i have some int, by doing this
name = "#{variable1}#{variable2}"
name2 = "#{variable2}#{variable1}"
it´s a simple example with just two variables but thats the idea, what im trying to make. i am doing all the possibilities one by one, even when is more than two variables but there are many combinations. Is there an easy way to do it or i have to do it one by one?Also, do i need to write the quotation marks separately or that way is fine?
Is this what you had in mind?
variable1 = "cat"
variable2 = 9
variable3 = "lives"
arr = [variable1, variable2, variable3]
#=> ["cat", 9, "lives"]
arr.join
#=> "cat9lives"
Put all or some of these variables into an array which will produce the combinations easier.
s1 = 'a'
s2 = 'b'
s3 = 'c'
n = 8
[s1, s2, s3, n].combination(3).map(&:join)
=> ["abc", "ab8", "ac8", "bc8"]
Above example assumes that you will pick any of 3 variables from the array and calculate the combinations. You may want to adjust that number to meet your needs.
The whole idea of programming is not doing all possibilities one by one. "there are many combinations": they look like permutations to me. If that is the case:
var1 = "aa"
var2 = "bb"
var3 = 2
res = [var1, var2, var3].permutation.map{|perm| perm.join}
p res #=> ["aabb2", "aa2bb", "bbaa2", "bb2aa", "2aabb", "2bbaa"]

Search String By SubWords

What Kind of algorithms + data structures that would help me to do that?
Having a file contains like 10000~ lines loaded in memory in a ordered set. With a given search string I want to be able to get all the lines that have words prefixed with words found in search string. Well let me give an example to clarify this:
Lines:
"A brow Fox flies."
"Boxes are full of food."
"Cats runs slow"
"Dogs hates eagles"
"Dolphins have eyes and teath"
Cases 1:
search string = "fl b a"
"A brow Fox flies."
Explanation: search string have three words "fl", "b", and "a" and
the only string that have some words that are prefixed with words
from the search string is line 1.
Case 2:
search string "e do ha"
"Dogs hates eagles", "Dolphins have eyes and teath"
Solution
(fast enough for me it took about 30ms~(including sorting the final result) on my pc on a set of 10k lines 3 words each line)
I used a trie suggested in answer.
And some other hacky methods to be able to filter out duplicate and false positive results (mainly used hash sets for this).
I think what you're probably wanting is a trie. Construct one for the set of all words in your document, and have each leaf point to a hashset containing the indices of the lines in which the key of the leaf appears.
To execute a search, you'd use each fragment of the search string to navigate to a node in the tree and take the union over the hashsets of all leaves in that node's subtree. Then you'd take the intersection of those unions over the set of fragments to get the list of lines satisfying the search string.
Here is my 2 cents:
class DicVal
{
public int OriginalValue;
public int CurrentValue;
public int LineNumber;
}
private static void Main()
{
var a = "A brow Fox flies.\r\n" +
"Boxes are full of food.\r\n" +
"Cats runs slow\r\n" +
"Dogs hates eagles\r\n" +
"A brow Fox flies. AA AB AC\r\n" +
"Dolphins have eyes and teath";
var lines = a.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
var dic = new Dictionary<string, DicVal>
{
{"fl", new DicVal { OriginalValue = 1, LineNumber = -1}},
{"b", new DicVal { OriginalValue = 1, LineNumber = -1}},
{"a", new DicVal { OriginalValue = 4, LineNumber = -1}}
};
var globalCount = dic.Sum(x => x.Value.OriginalValue);
var lineNumber = 0;
foreach(var line in lines)
{
var words = line.Split(' ');
var currentCount = globalCount;
foreach (var word in words.Select(x => x.ToLower()))
{
for (var i = 1; i <= word.Length; i++)
{
var substr = word.Substring(0, i);
if (dic.ContainsKey(substr))
{
if (dic[substr].LineNumber != lineNumber)
{
dic[substr].CurrentValue = dic[substr].OriginalValue;
dic[substr].LineNumber = lineNumber;
}
if (dic[substr].CurrentValue > 0)
{
currentCount--;
dic[substr].CurrentValue--;
}
}
}
}
if(currentCount == 0)
Console.WriteLine(line);
lineNumber++;
}
}
Not going to explain much, as code is the best documentation :P.
Output: A brow Fox flies. AA AB AC
Assuming you implement everything efficiently, the running time will be as good as possible, since you need to read every word at least ONCE.
Further optimization can be done and apply threading. You can view into PARALLEL AGGREGATION concept, as this problem can be parallelized easily.
Here's a fairly simple implementation that should be appropriate for your use case. The idea is that you can store all combinations of short prefixes for each line (and for each query) since you only have 10,000 lines and assuming each line doesn't contain too many words. Now look up each hash generated for the query string. For each hash match, we then check for an exact match. For my example code I consider only prefixes of length 1, however you could repeat this approach for prefixes of length 2 & 3 provided the prefixes in your query have those lengths too.
__author__ = 'www.google.com/+robertking'
from itertools import combinations
from collections import defaultdict
lines = [
"A brow Fox flies.",
"Boxes are full of food.",
"Cats runs slow",
"Dogs hates eagles",
"Dolphins have eyes and teath"
]
lines = [line.lower() for line in lines]
def short_prefixes(line):
for word in line.split():
yield word[:1]
def get_hashes(line):
starts = list(short_prefixes(line))
for prefixes_in_hash in range(1, min(4, len(starts))):
for hash_group in combinations(starts, r=prefixes_in_hash):
yield tuple(sorted(hash_group))
def get_hash_map():
possible_matches = defaultdict(list)
for line_pos, line in enumerate(lines):
for hash in get_hashes(line):
possible_matches[hash].append(line_pos)
return possible_matches
possible_matches = get_hash_map()
def ok(line, q):
return all(line.startswith(prefix) or ((" " + prefix) in line) for prefix in q)
def query(search_string):
search_string = search_string.lower()
q = search_string.split()
hashes = set(get_hashes(search_string))
possible_lines = set()
for hash in hashes:
for line_pos in possible_matches[hash]:
possible_lines.add(line_pos)
for line_pos in possible_lines:
if ok(lines[line_pos], q):
yield lines[line_pos]
print(list(query("fl b a")))
#['a brow fox flies.']

Comparing more than one object properties in separate arrays

I am trying to figure out a way to iterate through and remove duplicate records from four different sources.
first_source = [#<Customer:0x007f911e307ad0 #id="123", #name="Whitehall">,# <Customer:0x007f911e307ad0 #id="124", #name="Whitehall">#<Customer:0x007f911e307ad0 #id="125", #name="Whitehall">]
second_source = [#<Customer:0x007f911e307ad0 #id="5000", #name="Whitehall">,#<Customer:0x007f911e307ad0 #id="5500", #name="Whitehall">#<Customer:0x007f911e307ad0 #id="123", #name="Whitehall">]
third_source = [#<Customer:0x007f911e307ad0 #id="800", #name="Whitehall">,#<Customer:0x007f911e307ad0 #id="5000", #name="Whitehall">#<Customer:0x007f911e307ad0 #id="124", #name="Whitehall">]
fourth_source = [#<Customer:0x007f911e307ad0 #id="4300", #name="Whitehall">,#<Customer:0x007f911e307ad0 #id="800", #name="Whitehall">#<Customer:0x007f911e307ad0 #id="125", #name="Whitehall">]
I tried
customers = []
dup_customers = first_source + second_source + third_source + fourth_source
dup_customers.combination(2).each do |cs1, cs2|
customers << cs1 unless cs1.id != cs2.id
end
But this really did not work.
Can someone help me suggest a way/strategy for traversing through these four collections and finding the Customer id's that are equal and then doing something with it?
How about Array#uniq?
customers = (first_source + second_source + third_source + fourth_source).uniq
uniq discards duplicates by element-wise comparison using Object#eql?, so for this method to work, you would need to implement Customer#eql?.
class Customer
def eql?(other)
id == other.id #or however you define equality
end
end
dup_customers =
[first_source, second_source, third_source, fourth_source]
.combination(2).flat_map{|s1, s2| s1 & s2}
Overriding eql as #pje does is not necessary. uniq takes a block (last example):
customers = [first_source ,second_source, third_source, fourth_source ].flatten
p customers.uniq{|c| c.id}
You can use Array#| (union operator):
customers = first_source | second_source | third_source | fourth_source
It returns the result of the merging of the two arrays while removing duplicates:
["a", "b", "c" ] | [ "c", "d", "a" ]
#=> [ "a", "b", "c", "d" ]

Resources