Stylus concatenate variable and string - stylus

Following code
for $i in (1..81)
.block:nth-child({$i})
transition transform 500ms ease $i\s
will be compiled to
.block:nth-child(1) {
transition: transform 500ms ease 1 s;
}
......
But that space between number and seconds is redundant!
How can I remove it?

One possible approach:
for $i in (1..81)
.block:nth-child({$i})
transition transform 500ms ease 1s * $i
That's actually quite similar to the example given in Selector Interpolation section of Stylus documentation.

You can use the unit() function:
for $i in (1..81)
.block:nth-child({$i})
transition transform 500ms ease unit($i, 's')

Related

Check whether an array contains a value from another array

I have an array of objects, and an array of acceptable return values for a particular method. How do I reduce the array of objects to only those whose method in question returns a value in my array of acceptable values?
Right now, I have this:
my #allowed = grep {
my $object = $_;
my $returned = $object->method;
grep {
my $value = $_;
$value eq $returned;
} #acceptableValues;
} #objects;
The problem is that this is a compound loop, which I'd like to avoid. This program is meant to scale to arbitrary sizes, and I want to minimize the number of iterations that are run.
What's the best way to do this?
You could transform the accepted return values into a hash
my %values = map { $_ => 1 } #acceptedValues;
And grep with the condition that the key exists instead of your
original grep:
my #allowed = grep $values{ $_->method }, #objects;
Anyway, grep is pretty fast in itself, and this is just an idea of a
common approach to checking if an element is in an array. Try not to
optimize what's not needed, since it would only be worth in really big
arrays. Then you could for example sort the accepted results array and
use a binary search, or cache results if they repeat. But again, don't
worry with this kind of optimisation unless you're dealing with hundreds
of thousands of items — or more.
Elements supposed to be present in given arrays seems unique. So, I will make a hash containing the count of elements from both arrays. If there is any element with count greater than 1, it means its present in both the arrays.
my %values;
my #allowed;
map {$values{$_}++} (#acceptableValues, #objects);
for (keys %values) {
push #allowed, $_ if $values{$_} > 1;
}

In Ruby, how do I check if at least 80% of elements in an array match a pattern?

I'm using Ruby 2.4. How do I check if at least 80% of my elements in an array match a certain pattern? I want to see if each element matches the regex
/\d\d?\s*-\s*\d\d?/
You can use Enumerable#grep in conjunction with simple math:
array.grep(/\d\d?\s*-\s*\d\d?/).size / array.size.to_f >= 0.8
To shorten this further you can use Numeric#quo or Numeric#fdiv:
array.grep(/\d\d?\s*-\s*\d\d?/).size.quo(array.size) >= 0.8
If performance does matter, you don't need to check all the elements to know if at least 80% of them are maching a condition
With ruby 2.3 this implementation is a bit faster than the count solution and twice faster than the grep solution :
def pareto_match(array, proportion: 0.8)
min_success= (array.count * proportion).round(4)
max_failures= (array.count * (1 - proportion)).round(4)
success= 0
failure= 0
array.each do |element|
if yield(element)
success+= 1
return true if success >= min_success
else
failure+= 1
return false if failure > max_failures
end
end
end
pareto_match(array){|e| e =~ /\d\d?\s*-\s*\d\d?/}
I would write:
(array.count{|item| item =~ /\d\d?\s*-\s*\d\d?/} / array.size) >= 0.8

Maya M.E.L : Is it possible to store an array of type joint?

Hi I am a new MEL user and have been playing around , searching around but can't figure this out:
I was trying to move all the joint transform rotation values to the joint orient values so that i can clean up the attributes of the transforms without losing joint orientation, my mel attempt for it was this:
string $joints[]=`ls -type "joint"`;
//print($joints);
int $jnt_count = size($joints);
for ($i = 0; $i <= $jnt_count; $i++)
{
int $attr1 = `getAttr $joints[i].rotateX`;
int $attr2 = `getAttr $joints[i].rotateY`;
int $attr3 = `getAttr $joints[i].rotateZ`;
setAttr $joints[i].jointOrientX $attr1;
setAttr $joints[i].jointOrientY $attr2;
setAttr $joints[i].jointOrientZ $attr3;
}
I was hoping with the array of all the joints (names), i could change their attributes in that manner by calling to them one by one, but it seems I cannot do it that way
However! When I do an objectType $joints[1] to test, it still return a type "joints" , so I don't get why the value of the array is type joints, but I can't access the joint's joint.XXX attributes, can someone enlighten me on this matter or point me in the right direction?
Must appreciated!
Dave
In mel you only ever get strings, floats or integers to work with - they are the names of objects in the scene, but not wrappers or handles to the objects themselves.
In your specific example, you'd want this:
string $joints[]=`ls -type "joint"`;
int $jnt_count = size($joints);
for ($i = 0; $i <= $jnt_count; $i++)
{
float $attr1 = `getAttr ($joints[$i] + ".rotateX")`;
// etc. See how this is done by adding the strings to
// create the string "youJointHere.rotateX", periods and all...
// the parens make sure string is composed before the command is called
setAttr ($joints[$i] + ".jointOrientX") $attr1;
// etc. Same trick
}
If you're new to this, you can save yourself a world of hurt and jumping straight to maya Python -- it's a lot more powerful than mel. The optional Pymel makes it even easier - the original code you posted is more or less what Pymel lets you do.
EDIT: forgot the $ variable identifier and parens in the first version.
As theodox pointed out, Pymel makes this much easier! And is closer to your post.
joints = pm.ls(sl=1, type='joints')
jountCount = len(joints)
for i in range(jointCount):
rot = joints[i].r.get()
joints[i].jointOrient.set([rot[0], rot[1], rot[2]])
In my opinion, Pymel is much more superior, as it's easier to read, easier to write and derived from the api as mel is, it performs just as fast :)

In Perl, how do I check to see if an array matches a value listed at least once within it's contents?

I've never really worked with Perl before (avoided it where I could) and so my knowledge is sparse on the topic.
I know the script I am looking at has an array of ProductID values in #::s_Ship_sShipProducts.
I was attempting to see if any of the ProductIDs in the array began with either B or S and execute a function if so, else do another function. But what I ended up with was for each ProductID do the statement. This is what I (admittedly salvaged) had.
my $i;
for $i (0 .. $#::s_Ship_sShipProducts) # for each product
if ($::s_Ship_sShipProducts[$i] =~ /^(B|S)/) # Determine if B or S product
{
if (defined $phashBandDefinition->{'FreeOver'} && CalculatePrice() > 250)
{$nCost = 0;}
}
else {
if (defined $phashBandDefinition->{'FreeOver'} && CalculatePrice() > $phashBandDefinition->{'FreeOver'})
{$nCost = 0;}
}
How could I change this so that the array was inspected to see if any ProductID was true and return true, or false if nothing matched? Then execute the appropriate function based on true or false? I have done some reading, but am still in the dark. Thanks for your time.
If the array is not too big (or you don't care THAT much about performance), you can check if there are any matching values via grep:
if (my #matching_elements = grep { /^(B|S)/ } #::s_Ship_sShipProducts) {
# Better yet use /^[BS]/ expression - more idiomatic/readable
print "Found B/S\n";
} else {
print "NOT Found B/S\n";
}
When done, #matching_elements would contain a list of matching IDs.
In the rare case when the array IS too big to scan through entirely and you only need to find the first occurance, you can use any of the array search optimization strategies discussed in binary search in an array in Perl
By the way, your approach to search works perfectly fine, you merely need to quit the loop once you found - and to boot, is one of those optimized approaches shown in the list above:
for my $i (0 .. $#::s_Ship_sShipProducts) # for each product
if ($::s_Ship_sShipProducts[$i] =~ /^[BS]/) { # Determine if B or S product
# Execute your logic here
last; # Found, get out of the loop.
}
}
NOTE: In Perl 5.10 and above, you can - instead of grep - use a so-called "smart match" operator ~~:
if (#::s_Ship_sShipProducts ~~ /^(B|S)/) {
# Your logic
}
I'm not quite sure if I'm following your question, but I think you are looking for grep.
my #matched_products = grep(/^(B|S)/,#::s_Ship_sShipProducts);

In Perl, how do I create a hash whose keys come from a given array?

Let's say I have an array, and I know I'm going to be doing a lot of "Does the array contain X?" checks. The efficient way to do this is to turn that array into a hash, where the keys are the array's elements, and then you can just say if($hash{X}) { ... }
Is there an easy way to do this array-to-hash conversion? Ideally, it should be versatile enough to take an anonymous array and return an anonymous hash.
%hash = map { $_ => 1 } #array;
It's not as short as the "#hash{#array} = ..." solutions, but those ones require the hash and array to already be defined somewhere else, whereas this one can take an anonymous array and return an anonymous hash.
What this does is take each element in the array and pair it up with a "1". When this list of (key, 1, key, 1, key 1) pairs get assigned to a hash, the odd-numbered ones become the hash's keys, and the even-numbered ones become the respective values.
#hash{#array} = (1) x #array;
It's a hash slice, a list of values from the hash, so it gets the list-y # in front.
From the docs:
If you're confused about why you use
an '#' there on a hash slice instead
of a '%', think of it like this. The
type of bracket (square or curly)
governs whether it's an array or a
hash being looked at. On the other
hand, the leading symbol ('$' or '#')
on the array or hash indicates whether
you are getting back a singular value
(a scalar) or a plural one (a list).
#hash{#keys} = undef;
The syntax here where you are referring to the hash with an # is a hash slice. We're basically saying $hash{$keys[0]} AND $hash{$keys[1]} AND $hash{$keys[2]} ... is a list on the left hand side of the =, an lvalue, and we're assigning to that list, which actually goes into the hash and sets the values for all the named keys. In this case, I only specified one value, so that value goes into $hash{$keys[0]}, and the other hash entries all auto-vivify (come to life) with undefined values. [My original suggestion here was set the expression = 1, which would've set that one key to 1 and the others to undef. I changed it for consistency, but as we'll see below, the exact values do not matter.]
When you realize that the lvalue, the expression on the left hand side of the =, is a list built out of the hash, then it'll start to make some sense why we're using that #. [Except I think this will change in Perl 6.]
The idea here is that you are using the hash as a set. What matters is not the value I am assigning; it's just the existence of the keys. So what you want to do is not something like:
if ($hash{$key} == 1) # then key is in the hash
instead:
if (exists $hash{$key}) # then key is in the set
It's actually more efficient to just run an exists check than to bother with the value in the hash, although to me the important thing here is just the concept that you are representing a set just with the keys of the hash. Also, somebody pointed out that by using undef as the value here, we will consume less storage space than we would assigning a value. (And also generate less confusion, as the value does not matter, and my solution would assign a value only to the first element in the hash and leave the others undef, and some other solutions are turning cartwheels to build an array of values to go into the hash; completely wasted effort).
Note that if typing if ( exists $hash{ key } ) isn’t too much work for you (which I prefer to use since the matter of interest is really the presence of a key rather than the truthiness of its value), then you can use the short and sweet
#hash{#key} = ();
I always thought that
foreach my $item (#array) { $hash{$item} = 1 }
was at least nice and readable / maintainable.
There is a presupposition here, that the most efficient way to do a lot of "Does the array contain X?" checks is to convert the array to a hash. Efficiency depends on the scarce resource, often time but sometimes space and sometimes programmer effort. You are at least doubling the memory consumed by keeping a list and a hash of the list around simultaneously. Plus you're writing more original code that you'll need to test, document, etc.
As an alternative, look at the List::MoreUtils module, specifically the functions any(), none(), true() and false(). They all take a block as the conditional and a list as the argument, similar to map() and grep():
print "At least one value undefined" if any { !defined($_) } #list;
I ran a quick test, loading in half of /usr/share/dict/words to an array (25000 words), then looking for eleven words selected from across the whole dictionary (every 5000th word) in the array, using both the array-to-hash method and the any() function from List::MoreUtils.
On Perl 5.8.8 built from source, the array-to-hash method runs almost 1100x faster than the any() method (1300x faster under Ubuntu 6.06's packaged Perl 5.8.7.)
That's not the full story however - the array-to-hash conversion takes about 0.04 seconds which in this case kills the time efficiency of array-to-hash method to 1.5x-2x faster than the any() method. Still good, but not nearly as stellar.
My gut feeling is that the array-to-hash method is going to beat any() in most cases, but I'd feel a whole lot better if I had some more solid metrics (lots of test cases, decent statistical analyses, maybe some big-O algorithmic analysis of each method, etc.) Depending on your needs, List::MoreUtils may be a better solution; it's certainly more flexible and requires less coding. Remember, premature optimization is a sin... :)
In perl 5.10, there's the close-to-magic ~~ operator:
sub invite_in {
my $vampires = [ qw(Angel Darla Spike Drusilla) ];
return ($_[0] ~~ $vampires) ? 0 : 1 ;
}
See here: http://dev.perl.org/perl5/news/2007/perl-5.10.0.html
Also worth noting for completeness, my usual method for doing this with 2 same-length arrays #keys and #vals which you would prefer were a hash...
my %hash = map { $keys[$_] => $vals[$_] } (0..#keys-1);
Raldi's solution can be tightened up to this (the '=>' from the original is not necessary):
my %hash = map { $_,1 } #array;
This technique can also be used for turning text lists into hashes:
my %hash = map { $_,1 } split(",",$line)
Additionally if you have a line of values like this: "foo=1,bar=2,baz=3" you can do this:
my %hash = map { split("=",$_) } split(",",$line);
[EDIT to include]
Another solution offered (which takes two lines) is:
my %hash;
#The values in %hash can only be accessed by doing exists($hash{$key})
#The assignment only works with '= undef;' and will not work properly with '= 1;'
#if you do '= 1;' only the hash key of $array[0] will be set to 1;
#hash{#array} = undef;
You could also use Perl6::Junction.
use Perl6::Junction qw'any';
my #arr = ( 1, 2, 3 );
if( any(#arr) == 1 ){ ... }
If you do a lot of set theoretic operations - you can also use Set::Scalar or similar module. Then $s = Set::Scalar->new( #array ) will build the Set for you - and you can query it with: $s->contains($m).
You can place the code into a subroutine, if you don't want pollute your namespace.
my $hash_ref =
sub{
my %hash;
#hash{ #{[ qw'one two three' ]} } = undef;
return \%hash;
}->();
Or even better:
sub keylist(#){
my %hash;
#hash{#_} = undef;
return \%hash;
}
my $hash_ref = keylist qw'one two three';
# or
my #key_list = qw'one two three';
my $hash_ref = keylist #key_list;
If you really wanted to pass an array reference:
sub keylist(\#){
my %hash;
#hash{ #{$_[0]} } = undef if #_;
return \%hash;
}
my #key_list = qw'one two three';
my $hash_ref = keylist #key_list;
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my #a = qw(5 8 2 5 4 8 9);
my #b = qw(7 6 5 4 3 2 1);
my $h = {};
#{$h}{#a} = #b;
print Dumper($h);
gives (note repeated keys get the value at the greatest position in the array - ie 8->2 and not 6)
$VAR1 = {
'8' => '2',
'4' => '3',
'9' => '1',
'2' => '5',
'5' => '4'
};
You might also want to check out Tie::IxHash, which implements ordered associative arrays. That would allow you to do both types of lookups (hash and index) on one copy of your data.

Resources