How this where clause is working?
(digit, index) => digit.Length < index
Code
public void Linq5()
{
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var shortDigits = digits.Where((digit, index) => digit.Length < index);
Console.WriteLine("Short digits:");
foreach (var d in shortDigits)
{
Console.WriteLine("The word {0} is shorter than its value.", d);
}
}
Source
Edited for clarification
As per Iswanto San
(digit, index) => digit.Length < index
declaration of variable :
(digit, index) -- digit as array of digits
Condition (like where clause in SQL):
digit.Length < index
Correct if am I wrong?
if I am going right then what is the role of =>
This will return all elements from the list, which Length is lower then position in that list.
MSDN: Enumerable.Where<TSource> Method (IEnumerable<TSource>, Func<TSource, Int32, Boolean>)
The first argument of predicate represents the element to test. The second argument represents the zero-based index of the element within source.
It should return these elements:
{ "five", "six", "seven", "eight", "nine" }
It selects strings which length is smaller than it's index in the array.
This:
(digit, index) => digit.Length < index
digit will refer to array content (in this case digits), the datatype is String.
index will refer to array index, the datatype is int.
So that condition will output the array content that has length less than it's index (position).
For example:
digits="zero", index=0 => false, length=4, index=0
digits="one", index=1 => false, length=3, index=1
digits="two", index=2 => false, length=3, index=2
digits="three", index=3 => false, length=5, index=3
digits="four", index=4 => false, length=4, index=4
digits="five", index=5 => true, length=4, index=5
More: Enumerable.Where
Related
Alright I've been working on this coding challenge for quite some time and I guess it's officially time for me to raise the flag. Help!
My task is to create a function that takes a Roman numeral as its argument and returns its value as a numeric decimal integer.
So far I've successfully created a hash mapping the numbers to its numeric values. I've also created an empty array roman_no to pass the key/value pair through.
What I am struggling with is writing the expression. Below is the full code:
def solution(roman)
# take a value of a roman numeral
roman_numeral =
{
1000 => "M",
900 => "CM",
500 => "D",
400 => "CD",
100 => "C",
90 => "XC",
50 => "L",
40 => "XL",
10 => "X",
9 => "IX",
5 => "V",
4 => "IV",
1 => "I"
}
roman_no = Array.new
roman_numeral.each do | key, value |
while
"#{roman}" >= "#{key}"
+= roman_no
"#{roman}" -= "#{key}"
end
return roman_no
solution('XXI')
How can I write an argument that will take the value from roman_numeral and return its number counter part?
for example:
solution('XXI') # should return 21
def solution(roman)
mapping = {
"M"=>1000,
"D"=>500,
"C"=>100,
"L"=>50,
"X"=>10,
"V"=>5,
"I"=>1
}
# split string into characters
roman.chars.map do |l|
mapping[l] # replace character with integer value
end
.compact # removes potential nils caused by invalid chars
# Splits array into chunks so that we can handle numerals such as IIX
.chunk_while do |i,j|
i <= j #
end
# each chunk will be an array like [10, 10, 100] or [1, 1, 1, 1]
.map do |chunk|
if chunk.first < chunk.last
chunk.reverse.inject(:-) # handles numerals such as IIX with subtraction
else
chunk.sum # chunk is just a list of numerals such as III
end
end
.sum # sums everything up
end
Basically, I have an array which contains 3 hashes. I want to count and return each key and value inside the hashes, which include any duplicates. The code is below, I have done the first draft of the code as you can see for yourself below.
my_array = [{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}]
#Count the number of times each element appears inside the hash
#so the output should have the number of times the :names, "blake" and "ashley" element appears
#EXPECTED OUTPUT: :name = 3, "blake" = 2, "ashley" = 1
def getOccurances(array)
array.group_by{|v| v[:name]}.map{|k,v| {name: k, count: v.length}}
end
getOccurances(my_array)
#ACTUAL OUTPUT: {:name => "blake", :count => 2}, {:name => "ashley", :count => 1}
You can map each Hash to an Array of [key, val] pairs, then flatten and each occurrence:
[{:name => "blake"}, {:name => "blake"}, {:name => "ashley"}].
map(&:to_a).flatten.
reduce(Hash.new { 0 }) {|o, v| o[v] += 1; o }
The argument to reduce is a Hash initialized with a block, so the default value of uninitialized keys is 0; we simply iterate through the flattened entries and accumulate a count of values.
my_array.each_with_object(Hash.new(0)) { |g,h| h[g[:name]] += 1 }.
map { |k,v| { name: k, count: v } }
#=> [{:name=>"blake", :count=>2}, {:name=>"ashley", :count=>1}]
Note:
my_array.each_with_object(Hash.new(0)) { |g,h| h[g[:name]] += 1 }
#=> {"blake"=>2, "ashley"=>1}
This question already has answers here:
What is the most ruby-ish way of accessing nested hash values at arbitrary depths? [duplicate]
(4 answers)
How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?
(16 answers)
Closed 7 years ago.
In Ruby, I want to do something like this,
I have a hash of hash built like this.
h = {1 => {2 => {3 => "three"}},'a' => { 'b' => { 'c' => "basd"}}}
=> {"a"=>{"b"=>{"c"=>"basd"}}, 1=>{2=>{3=>"three"}}}
If I have an array with values like this.
a = [1, 2, 3]
I want to have a method which will use the array values to index nested keys in my hash and return the value pointed by last key (as guided by previous array/keys)
for eg.
getHashValue([1,2,3]) should return "three" => h[1][2][3]
if a = ['a','b', 'c'] then the return value should be basd.
How to get this done?
And then there's:
keys.inject(hash, :fetch)
or for earlier Ruby versions:
keys.inject(hash) {|h, k| h[k]}
If you did want to use recursion, a more Rubyesque approach would be:
def get_value(obj, keys)
keys.empty? ? obj : get_value(obj[keys[0]], keys[1..-1])
end
Simple recursion
def getValue(hash, keys, i = 0)
if i + 1 < keys.length
getValue(hash[keys[i]], keys, i + 1)
else
hash[keys[i]]
end
end
getValue(h, [1,2,3]) => "three"
getValue(h, ['a','b','c']) => "basd"
Ruby 2.3.0 introduced a new method called dig on both Hash and Array that solves this problem entirely.
It returns nil if an element is missing at any level of nesting.
h1 = {}
h2 = { a: {} }
h3 = { a: { b: {} } }
h4 = { a: { b: { c: 100 } } }
h1.dig(:a, :b, :c) # => nil
h2.dig(:a, :b, :c) # => nil
h3.dig(:a, :b, :c) # => nil
h4.dig(:a, :b, :c) # => 100
h = {1 => {2 => {3 => "three"}},'a' => { 'b' => { 'c' => "basd"}}}
a = ['a','b', 'c']
a.inject(h, :[]) # => "basd"
h = {1 => {2 => {3 => "three"}},'a' => { 'b' => { 'c' => "basd"}}}
a = [1, 2, 3]
a.inject(h, :[]) # => "three"
How would you sort an array of string by length in ColdFusion?
In PHP, one can use usort as demonstrated here: PHP: Sort an array by the length of its values?
Does ArraySort() in CF10 support passing in a comparator function like usort?
The above answer has an error, here is the correct way to use arraysort to sort by string length:
<cfscript>
data = [ "bb", "a", "dddd", "ccc" ];
arraySort( data, function( a, b ) {
return len(a) - len(b);
});
</cfscript>
The comparator for this function should return a number either < 0 (less than), 0 (equal) or > 0 (greater than), not a boolean. Also see the arraySort docs.
I guess this is not going to be most flexible or even effective solution, but I was interested in the shortest version which uses built-in CFML sorting... Without comments it's just 13 lines of code :)
source = ["bb", "a", "ffff", "ccc", "dd", 22, 0];
lengths = {};
result = [];
// cache lengths of the values with index as key
for (i=1; i LTE ArrayLen(source); i++) {
lengths[i] = Len(source[i]);
}
// sort the values using 'numeric' type
sorted = StructSort(lengths, "numeric", "asc");
// populate results using sorted cache indexes
for (v in sorted) {
ArrayAppend(result, source[v]);
}
Result is ["a",0,"bb",22,"dd","ccc","ffff"]
You can use a quick sort algorithm along with your own custom comparator, similar to how Java's comparators work.
You can find a quickSort UDF here: http://cflib.org/udf/quickSort.
You'll need to define your own comparator to tell the function how it should do the sorting. Below is a working example. Note that you'll need in include the UDF in your page so that the quickSort function is available.
strings = ["bb", "a", "ccc"];
WriteOutput(ArrayToList(quickSort(strings, descStringLenCompare)));
//outputs a,bb,ccc
WriteOutput(ArrayToList(quickSort(strings, ascStringLenCompare)));
//outputs ccc,bb,a
//Ascending comparator
Numeric function ascStringLenCompare(required String s1, required String s2)
{
if (Len(s1) < Len(s2)){
return -1;
}else if (Len(s1) > Len(s2)) {
return 1;
}else{
return 0;
}
}
//Descending comparator
Numeric function descStringLenCompare(required String s1, required String s2)
{
if (Len(s1) < Len(s2)){
return 1;
}else if (Len(s1) > Len(s2)) {
return -1;
} else {
return 0;
}
}
In Coldfusion 10 or Railo 4, you can use the Underscore.cfc library to write this in an elegant and simple way:
_ = new Underscore(); // instantiate the library
// define an array of strings
arrayOfStrings = ['ccc', 'a', 'dddd', 'bb'];
// perform sort
sortedArray = _.sortBy(arrayOfStrings, function (string) {
return len(string);
});
// sortedArray: ['a','bb','ccc','dddd']
The iterator function is called for each value in the array, and that value is passed in as the first argument. The function should return the value that you wish to sort on. In this case, we return len(string). _.sortBy always sorts in ascending order.
(Disclaimer: I wrote Underscore.cfc)
In CF10 you can indeed use a closure with ArraySort().
eg1. sort by length alone.
<cfscript>
data = [ "bb", "a", "dddd", "ccc" ];
arraySort( data, function( a, b ) {
return len(a) < len(b);
});
</cfscript>
data == [ "a", "bb", "ccc", "dddd" ]
eg2. sort by length and alphabetically when same length.
<cfscript>
data = [ "b", "a", "dddd", "ccc" ];
arraySort( data, function( a, b ) {
return len(a) == len(b) ? compare( a, b ) : ( len(a) > len(b) );
});
</cfscript>
data == [ "a", "b", "ccc", "dddd" ]
eg3. same, only reverse the order.
<cfscript>
data = [ "b", "a", "dddd", "ccc" ];
arraySort( data, function( a, b ) {
return len(a) == len(b) ? compare( b, a ) : ( len(a) < len(b) );
});
</cfscript>
data == [ "dddd", "ccc", "b", "a" ]
I have two collections that I want to intersect, and perform a sum operation on matching elements.
For example the collections are (in pseudo code):
col1 = { {"A", 5}, {"B", 3}, {"C", 2} }
col2 = { {"B", 1}, {"C", 8}, {"D", 6} }
and the desired result is:
intersection = { {"B", 4}, {"C", 10} }
I know how to use an IEqualityComparer to match the elements on their name, but how to sum the values while doing the intersection?
EDIT:
The starting collections haven't two items with the same name.
Let's say your input data looks like this:
IEnumerable<Tuple<string, int>> firstSequence = ..., secondSequence = ...;
If the strings are unique in each sequence (i.e there can be no more than a single {"A", XXX} in either sequence) you can join like this:
var query = from tuple1 in firstSequence
join tuple2 in secondSequence on tuple1.Item1 equals tuple2.Item1
select Tuple.Create(tuple1.Item1, tuple1.Item2 + tuple2.Item2);
You might also want to consider using a group by, which would be more appropriate if this uniqueness doesn't hold:
var query = from tuple in firstSequence.Concat(secondSequence)
group tuple.Item2 by tuple.Item1 into g
select Tuple.Create(g.Key, g.Sum());
If neither is what you want, please clarify your requirements more precisely.
EDIT: After your clarification that these are dictionaries - your existing solution is perfectly fine. Here's another alternative with join:
var joined = from kvp1 in dict1
join kvp2 in dict2 on kvp1.Key equals kvp2.Key
select new { kvp1.Key, Value = kvp1.Value + kvp2.Value };
var result = joined.ToDictionary(t => t.Key, t => t.Value);
or in fluent syntax:
var result = dict1.Join(dict2,
kvp => kvp.Key,
kvp => kvp.Key,
(kvp1, kvp2) => new { kvp1.Key, Value = kvp1.Value + kvp2.Value })
.ToDictionary(a => a.Key, a => a.Value);
This will give the result, but there are some caveats. It does an union of the two collections and then it groups them by letter. So if, for example, col1 contained two A elements, it would sum them together and, because now they are 2 A, it would return them.
var col1 = new[] { new { L = "A", N = 5 }, new { L = "B", N = 3 }, new { L = "C", N = 2 } };
var col2 = new[] { new { L = "B", N = 1 }, new { L = "C", N = 8 }, new { L = "D", N = 6 } };
var res = col1.Concat(col2)
.GroupBy(p => p.L)
.Where(p => p.Count() > 1)
.Select(p => new { L = p.Key, N = p.Sum(q => q.N) })
.ToArray();
The best I came up with until now is (my collections are actually Dictionary<string, int> instances):
var intersectingKeys = col1.Keys.Intersect(col2.Keys);
var intersection = intersectingKeys
.ToDictionary(key => key, key => col1[key] + col2[key]);
I'm not sure if it will perform well, at least is it readable.
If your intersection algorithm will result in anonymous type, i.e. ...Select(new { Key = key, Value = value}) then you can easily sum it
result.Sum(e => e.Value);
If you want to sum the "while" doing the intersection, add the value to the accumulator value when adding to the result set.