I was just playing around with hash tables and I did this:
$C = #{color = [System.Collections.ArrayList]#(#{y = 'yellow'},#{y = 'blue'})}
and I ended up with finding I can do:
($C.color.y).Get(1) or ($C.color.y).Item(1) and it does exactly the same thing.
I also found even though the autocomplete doesn't show you can do this you can:
($C.color.y).Get(0).Contains('yellow')
($C.color.y).Get(1).Contains('blue')
The Get and Item methods appear to be interchangeable what is the difference between them?
I did check the hash codes they are the same.
($C.color.y).Get(1).GetHashCode() or ($C.color.y).Item(1).GetHashCode()
Related
I want to duplicate a list of objects. I want to do some things to to that dupliucate but not affect the original list.
Heres my code:
var tempHolidays = <Holiday>[];
tempHolidays = holidays;
tempHolidays[widget.index].start = widget.start;
tempHolidays[widget.index].end = widget.end;
The results i'm seeing would suggest the actions carried out on tempHolidays are mirroring on holidays? Is this possible or do I have a bug elsewhere?
What you are doing is just passing the references of the initial list to the second.
To duplicate a list use toList(), it return a different List object with the same element of the original list
tempHolidays = holidays.toList()
Right now, I am just working with powershell, but I plan on porting this concept to JScript and using the .NET jsc with ActiveXObject('Access.Application'). I have opened my query using $accessapp.DoCmd.OpenQuery("MyQuery") and I can see that it is loaded using $accessapp.CurrentData.AllQueries("MyQuery"). I would like to use $accessapp.DoCmd.OutputTo(acOutputQuery, "MyQuery",<acFormat>, <file>), but for some reason, I keep getting the error:
Unexpected token 'acOutputQuery' in expression or statement
Just running $accessapp.DoCmd.OutputTo shows that is what is expected:
void OutputTo (AcOutputObjectType, Variant, Variant, Variant, Variant, Variant, Variant, AcExportQuality)
Every resource I have seen, including the Microsoft OutputTo documentation uses the acOutputObjectType in this manner, so I am completely stumped.
Okay, sorry it took me a while to get back. Thanks to #HansUp for leading me down the correct path. I Used the AcOutputObjectType enumeration link he posted as well as the MS Constants Enumeration. I'll give both a powershell example and an MS JScript one. I'll use acOutputQuery and xcFormatTXT as 1 and "MS-DOS" respectively here, but there are many others in the two links above.
powershell:
$acc = New-Object -com Access.Application
$acc.OpenCurrentDatabase("<path_to_file>.accdb")
$acc.DoCmd.OpenQuery("MyQuery")
$acc.DoCmd.OutputTo(1,"MyQuery","MS-DOS", "<path_to_output_file>.txt")
MS JScript:
function writeToTextFile(dbPath,queryName,outputPath){
var acc = new ActiveXObject("Access.Application"); //create new COM instance
acc.OpenCurrentDatabase(dbPath+".accdb"); //open the database
if(!acc.CurrentData.AllQueries(queryName).IsLoaded){
acc.DoCmd.OpenQuery(queryName); //load the query if it is not loaded yet
}
acc.DoCmd.OutputTo(1,queryName,"MS-DOS",outputPath+".txt"); //write to file
}
These two are kind of quick and dirty. Since I have this working in JScript now, I will probably make a writeToFile() function that takes the format as an argument. I considered using an object to map the name string to the enumeration, but I don't know how useful that would actually be. I suppose if you wanted, you could take the output object as an argument, too, but I only plan to use query objects for now.
Let me start by apologising that the below data structure probably isn't written correctly. I dynamically created the hashes in the code and I'm not very good at trying to represent what gets created.
$Sailings= #{
'Arrivals' = #{
$DynamicKey_booking_Ref = #{
'GoingTo' = 'Port1';
'Scheduled' = '09:05';
'Expected' = '10:09';
'Status' = 'Delayed'
};
'Departures' = #{
$DynamicKey_booking_Ref = #{
'ArrivingFrom' = 'Port1';
'Scheduled' = '09:05';
'Expected' = '09:05';
'Status' = 'OnTime'
};
}
}
I typically access the data like this. (hopefully that confirm the structure I'm using):
$Sailings.Arrivals.PDH083.GoingTo which returns "Port1"
$Sailings.Arrivals.PDH083.Scheduled which returns "09:05"
where PDH083 in this example is a dynamically created key based on a booking ref.
What I am trying to do is compare this structure with another identical structure but with potentially different values. E.g. are these two elements the same?
$Sailings.Arrivals.PDH083.GoingTo = "Port1"
$Output.Arrivals.PDH083.GoingTo = "Port5555"
If they're not the same capture the difference and the path/key that was different. Then report on them at the end.
What I'm struggling to write is a recursive loop that can walk down to the last element and then compare it to the $output. While my hashes are fixed now, I'd like to allow for the possibility that more nested hashes might be added lower down at a later date. Is this something that can be done easily?
I've used
($Sailings.Arrivals.keys | ? {$Output.Arrivals.keys -notcontains $_})
to show missing keys, but I just can't fathom a similar / efficient way of doing this for the values. I again can see I can use .values but it's still and element at a time.
Here is a semi recursive example, which returns string representations of the paths for all the leaves in the tree. Hope it gives you ideas:
$Sailings = #{
'Arrivals' = #{
'PDH083' = #{
'GoingTo' = 'Port1'
'Scheduled' = '09:05'
'Expected' = '10:09'
'Status' = 'Delayed'
}
}
'Departures' = #{
'PDH083' = #{
'ArrivingFrom' = 'Port1'
'Scheduled' = '09:05'
'Expected' = '09:05'
'Status' = 'OnTime'
}
}
}
function Roam($arg, $result="") {
if(!($arg -is [Hashtable])) {
return "$result/$arg"
}
foreach($pair in $arg.GetEnumerator()) {
Roam $pair.value "$result/$($pair.key)"
}
}
Roam $Sailings
The if is stop condition, the first thing you should ask when you are designing recursive operations: When I have a result?
Suppose you are standing on the roots of a huge tree, and you have been given a task of mapping routes to every single leave of that tree, every turn to the left or right on the branches from the trunk to a leave. Overwhelming, eh? But think instead about finding out a route to a single leave, whichever from the myriad.
You start climbing, and reach first branch. Will you turn to the left or right? Doesn't matter. You decide to take the left branch, and write down on piece of paper left. You reach next branch, and for matter of fun turn right, writing down right. After a few branches you are carrying notes like left, right, right, left, right and so on, until (because trees don't usually produce loops) eventually there is no more climbing but only a leave in font of you.
You've done it! You mapped the whole (and only one) path to this single leave, and can now jump down (hoping the tree is not too tall) and represent the paper containing the route to your adoring friends. Reaching the leave was the stop condition.
But how about the other leaves? Imagine you have a weird superpower of cloning yourself. When you reach a branch, you clone yourself and the paper you are carrying. If you turn right, you add that right turn to the notes, but the clone goes left, and writes down left instead. On next branch you again clone yourself and the paper, and write down your chosen direction, and the clone does the same for its direction. You don't have to worry about the clones, (Maybe you are a clone yourself!) just repeat that until you've reached the one leave and can jump out.
The $result argument is that piece of paper, and originally it doesn't came from anywhere, it's empty.
Because all the leaves in you data structure are strings, you could also write the if statement like:
if($arg -is [String])
How about GetEnumerator? Hashtables are normally not ordered in PowerShell. We can't pick first or second or sixth pair. But your data structure branches to more directions than left and right, so the Hashtable has to be ordered to an Array as a crowd of people to a queue, so we can use foreach loop to send our clones to their paths. (We could replace that loop with recursion, but let it be)
So in the function call Roam $pair.value "$result/$arg" the first argument is the branch ahead, and the second one is the piece of paper we just added the current direction.
Recommendation: You don't need to scramble it through, even the first few chapters are enlightening. Structure and Interpretation of Computer Programs https://mitpress.mit.edu/sicp/full-text/book/book.html
I have an index that looks like this:
index user_core
{
source = user_core_0
path = ...
charset-type = utf-8
min_infix_length = 3
enable_star = 1
}
We escape and wrap all of our searches in asterisks. Every so often, we'll come across a
very strange case in which something such as the following happens:
Search: mocuddles
Results: All users with nicknames containing "yellowstone".
This behavior seems unpredictable, but will happen every time on terms it does effect.
I've been told that there's no real way to debug Sphinx indexes. Is this true? Is there
any sort of "explain query" functionality?
I've confirmed at this point that these are instances of CRC32 hash collisions. Bummer.
I searched SO before asking this question, I am completely new to this and have no idea how to handle these errors. By this I mean Perl language.
When I put this
%name->{#id[$#id]} = $temp;
I get the error Using a hash as a reference is deprecated
I tried
$name{#id[$#id]} = $temp
but couldn't get any results back.
Any suggestions?
The correct way to access an element of hash %name is $name{'key'}. The syntax %name->{'key'} was valid in Perl v5.6 but has since been deprecated.
Similarly, to access the last element of array #id you should write $id[$#id] or, more simply, $id[-1].
Your second variation should work fine, and your inability to retrieve the value has an unrelated reason.
Write
$name{$id[-1]} = 'test';
and
print $name{$id[-1]};
will display test correctly
%name->{...}
has always been buggy. It doesn't do what it should do. As such, it now warns when you try to use it. The proper way to index a hash is
$name{...}
as you already believe.
Now, you say
$name{#id[$#id]}
doesn't work, but if so, it's because of an error somewhere else in the code. That code most definitely works
>perl -wE"#id = qw( a b c ); %name = ( a=>3, b=>4, c=>5 ); say $name{#id[$#id]};"
Scalar value #id[$#id] better written as $id[$#id] at -e line 1.
5
As the warning says, though, the proper way to index an array isn't
#id[...]
It's actually
$id[...]
Finally, the easiest way to get the last element of an array is to use index -1. The means your code should be
$name{ $id[-1] }
The popular answer is to just not dereference, but that's not correct. In other words %$hash_ref->{$key} and %$hash_ref{$key} are not interchangeable. The former is required to access a hash reference nested as an element in another hash reference.
For many moons it has been common place to nest hash references. In fact there are several modules that parse data and store it in this kind of data structure. Instantly depreciating the behavior without module updates was not a good thing. At times my data is trapped in a nested hash and the only way to get it is to do something like.
$new_hash_ref = $target_hash_ref->{$key1}
$new_hash_ref2 = $target_hash_ref->{$key2}
$new_hash_ref3 = $target_hash_ref->{$key3}
because I can't
foreach my $i(keys(%$target_hash_ref)) {
foreach(%$target_hash_ref->{$i} {
#do stuff with $_
}
}
anymore.
Yes the above is a little strange, but creating new variables just to avoid accessing a data structure in a certain way is worse. Am I missing something?
If you want one item from an array or hash use $. For a list of items use # and % respectively. Your use of # as a reference returned a list instead of an item which perl may have interpreted as a hash.
This code demonstrates your reference of a hash of arrays.
#!/usr/bin perl -w
my %these = ( 'first'=>101,
'second'=>102,
);
my #those = qw( first second );
print $these{$those[$#those]};
prints '102'