2014年12月

Having problems with python's random.shuffle

I would like to make a matrix whose lines are different permutations of the following vector=

[1,2,3,4,5,10,10,10,10,10]

I tried to use the random.shuffle function, but it seems that everytime I use that, It redefines all objects to which it is assigned. For example, I have tried the following:



vec=[1,2,3,4,5]  
for i in range(5):
vec.append(10)
Matpreferences=[]
for i in range(10):
random.shuffle(vec)
Matpreferences.append(vec)


But then I get a matrix with all lines equal.

eg:



[0, 0, 1.0, 0, 2.0, 3.0, 0, 0.5, 2.5, 1.5, 0]    
[0, 0, 1.0, 0, 2.0, 3.0, 0, 0.5, 2.5, 1.5, 0]
[0, 0, 1.0, 0, 2.0, 3.0, 0, 0.5, 2.5, 1.5, 0]
[0, 0, 1.0, 0, 2.0, 3.0, 0, 0.5, 2.5, 1.5, 0]
...


I even tried something like



Matpreferences=[]  
for i in range(10):
random.shuffle(vec)
a=vec
Matpreferences.append(a)


But it yields the same results. Is there any simple way to get around that?

Thanks a lot for any help given =)



Answers

You need to make a copy of vec before you shuffle it:



import random
vec=[1,2,3,4,5]
for i in range(5):
vec.append(10)
Matpreferences=[]
for i in range(10):
v = vec[:]
random.shuffle(v)
Matpreferences.append(v)


Explanation

From your code:



a=vec
Matpreferences.append(a)


Here, a points at the same data that vec points at. Consequently, when a is shuffled, so is vec and so is everything that points at vec.



By contrast, because of the subscripting [:], this code creates a new and independent copy of the data:



v = vec[:]


Because v is a separate and independent copy, shuffling v has no effect on vec.



Answers

Your adding an object reference to the list. Think of it as a pointer. Each vec that you add to Matpreferences points to the same instance.



Look at this example:



>>> vec = [1,2,3,4,5]
>>> vec2 = vec
>>> random.shuffle(vec)
>>> print vec
[2, 4, 3, 1, 5]
>>> print vec2
[2, 4, 3, 1, 5]
>>>


As you see, the content of vec and vec2 is the same even though I did not shuffle vec2.



what you need to do is to copy the content of vec into a new list and then add that list to Matpreferences



Replace your last line with



Matpreferences.append([x for x in vec])


or



Matpreferences.append(vec[:])


Answers

random.shuffle shuffles a list in place, so after each call, contents of vec gets shuffled. Note that vec is a reference to a list, so when you append vec 10 times in a list, it contains the same reference 10 times. All of them holds the same list. That's why you see the same list. vec is indeed shuffled 10 times, but you only see the last permutation when you print it.



To fix this, you'll need to make a new copy of vec each time, shuffle the copy and append that to Matpreferences. Or you can shuffle vec, then append a copy of it to Matpreferences.



Copying a list would be easy, the shortest one is, I think, using slicing:



Matpreferences.append(vec[:])




How to include a XML snippet into a XML document

I am using XML files as configuration files for my PowerShell scripts based on the blog post found at rkeithhill.wordpress.com. Some of my scripts shares the same settings and I would like to include those settings from an external XML file. What I have done is:





<?xml version="1.0" standalone="no" ?>
<!DOCTYPE doc [
<!ENTITY shareddata SYSTEM "shared.xml">
]>
<configuration >
<appSettings >
&shareddata;
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>


and the shared.xml file contains (one line only):



<add key="backhoe" value="Volvo BM 430 Hymas" />


Using the following code snippet I load the XML and print it to the console:



$config = [xml](get-content $path)
$text = $config.OuterXml
Write-Verbose "[LoadConfig] $text"


The output is:



VERBOSE: [LoadConfig] <?xml version="1.0" standalone="no"?>
<!DOCTYPE doc[
<!ENTITY shareddata SYSTEM "shared.xml">
]>
<configuration><appSettings>&shareddata;
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" /></appSettings> </configuration>


The way I load the XML does not include the content of shared.xml, but it does parse the DOCTYPE tag, since if I revert to an invalid file it will fail.





So, how could I get PowerShell to fully include the XML snippet, so that loadconfig will find the key and value for my backhoe as well?





I have also tried



$Document = ( Select-Xml -Path myfile.xml -XPath / ).Node


but it won't load anything as long as I have the &shareddata; in the config file:



Answers

I tried your example in C# and it doesn't work either. This works in C# however once you change shared.xml to contain TEST VALUE value (i.e. only simple values are allowed, not xml) but it still doesn't work in PS:



<configuration >
<appSettings >
<test>&shareddata;</test>
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>


Using this code:



$doc = new-object System.Xml.XmlDocument
$doc.Load("D:\config.xml")
$doc.configuration.appSettings.add

key value
--- -----
motorcycle Husqvarna TE610
car Ford Mondeo


The same examaple in C# works:



XmlDocument doc = new XmlDocument();
doc.Load("d:\\config.xml");
var x = doc["configuration"]["appSettings"]["test"];
Console.WriteLine(x.InnerText);


It outputs



TEST VALUE


It seems that Powershell sets doc.XmlResolver = null; option to prevent security related issues which you can see in PS as $doc.XmlResolver returning nothing. I didn't event succeed to manually set the resolver via $doc.XmlResolver = new-object System.Xml.XmlUrlResolver.



NOW,



you could use variable substitution to achieve the effect:



<configuration >
<appSettings >
$shared_xml
<add key="motorcycle" value="Husqvarna TE610" />
<add key="car" value="Ford Mondeo" />
</appSettings>
</configuration>

$shared_xml = Get-Content 'D:\shared.xml'
[xml]$config = $ExecutionContext.InvokeCommand.ExpandString((gc $path))


You could make this easier if you enumerate variables in config block and load appropriate files. You would be able then to not know in advance what files are included.



NOW,



this all seems like a lot of trouble unless there is some normal solution to the resolver problem. But the idea of keeping the config in XML is wrong on so many levels to be honest. Why use XML when you can use powershell config:



$config = @{ }
$config.motorcycle = 'Husqvarna TE610'
$config.car = 'Ford Mondeo'

$shared = @{}
$shared.backhoe = "Volvo BM 430 Hymas"

$config + $shared


Outputs



Name                           Value
---- -----
backhoe Volvo BM 430 Hymas
car Ford Mondeo
motorcycle Husqvarna TE610


You can make this follow "include" pattern such as:



config.ps1



$config = @{ 
motorcycle = 'Husqvarna TE610'
car = 'Ford Mondeo'
}
. shared1.ps1
...
. sharedN.ps1


sharedN.ps1



$config.sharedN_cfg1 = 1
$config.sharedN_cfg2 = 2


If you really need XML from that point you could use ConvertTo-CliXML and friends afterwards.



If you still want to pursue your direction I suggest you look at the XInclude (you need 3thd party assembly to make this work).





Where does this compiling error come from?

I am getting quite frustrated right now, and the main source of my frustration is the following error:



LogicalAutomaton.java:16: error: cannot find symbol
Cellular[i][j] = new Cellular (null, Cellular[i+1][j], null, Cellular[i][j+1]);
^
symbol: variable Cellular
location: class LogicalAutomaton


The class hierarchy is the following:



home --> code --> Automata --> automata


And here is the code:



This is the class Cellular.java, in home/code/Automata/automata:



package automata;

public class Cellular {

private int state;
private Cellular upper, lower, left, right;

public Cellular (Cellular upper, Cellular lower, Cellular left,Cellular right) {
this.state = 0;
this.upper = upper;
this.lower = lower;
this.left = left;
this.right = right;
}

}


And this is the class LogicalAutomaton.java, in home/code/Automata:



import automata.Cellular;
import java.util.Arrays;

public class LogicalAutomaton extends Cellular {

public static void main (String[] args) {

int n = 3;
Cellular[][] a = new Cellular[n][n];

for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == 0) {
if (j == 0) {
Cellular[i][j] = new Cellular (null, Cellular[i+1][j], null, Cellular[i][j+1]);
}
else {
if (j == n-1) {
Cellular[i][j] = new Cellular (null, Cellular[i+1][j], Cellular[i][j-1], null);
}
else {
Cellular[i][j] = new Cellular (null, Cellular[i+1][j], Cellular[i][j-1], Cellular[i][j+1]);
}
}
}
}
}

}

}


The code of LogicalAutomaton.java is much longer, but the main idea is to get access to the array of Cellular objects in order to initialize them, and each time I try to do this, it throws me said error. Funnily enough, the compiler does not lament the declaration of the Cellular array.



Do you have any idea where I might have done wrong?



Thank you in advance!



Edit:



Sorry for the clumsy question; here is part of the faulty code.



Answers

You define your array as



Cellular[][] a = new Cellular[n][n];


but then later on, you use



Cellular[i][j] = new Cellular (null, Cellular[i+1][j], null, Cellular[i][j+1]);


when in fact, you should be using



a[i][j] = new Cellular (null, Cellular[i+1][j], null, Cellular[i][j+1]);


The error message you are getting




LogicalAutomaton.java:16: error: cannot find symbol
Cellular[i][j] = new Cellular (null, Cellular[i+1][j], null, Cellular[i][j+1]);
^ symbol: variable Cellular location: class LogicalAutomaton




is saying I cannot find a variable named Cellular, not that I cannot find the class. This is because you have not defined a variable called Cellular, the variable you have defined is called a.



Answers

This problem is because of accessibility. The Cellular class is not accessible in the LogicalAutomoton class. Check your CLASSPATH variable and check whether the import statement is correct.





How to dynamically grab the first available number in a loop?

Been going at this for a while, figured I'd post it here for some help.



items = { '417': { a: 23, slot_position: 13 },
'419': { a: 28, slot_position: 2 },
'420': { a: 29, slot_position: 12 },
'421': { a: 29, slot_position: 3 },
'424': { a: 31, slot_position: 17 },
'425': { a: 32, slot_position: 7 },
'428': { a: 35, slot_position: 0 },
'429': { a: 36, slot_position: 0 },
'431': { a: 42, slot_position: 0 },
'432': { a: 40, slot_position: 0 },
'433': { a: 43, slot_position: 11 },
'434': { a: 44, slot_position: 0 },
'435': { a: 45, slot_position: 0 },
'436': { a: 47, slot_position: 0 },
'437': { a: 48, slot_position: 15 },
'438': { a: 48, slot_position: 1 },
'439': { a: 48, slot_position: 0 },
'440': { a: 48, slot_position: 14 },
'441': { a: 43, slot_position: 0 },
'442': { a: 44, slot_position: 0 },
'443': { a: 43, slot_position: 8 },
'444': { a: 37, slot_position: 0 },
'445': { a: 37, slot_position: 0 },
'446': { a: 37, slot_position: 0 },
'447': { a: 37, slot_position: 16 },
'451': { a: 50, slot_position: 5 },
'452': { a: 49, slot_position: 6 },
'453': { a: 39, slot_position: 20 },
'454': { a: 38, slot_position: 4 },
'455': { a: 19, slot_position: 19 },
'456': { a: 49, slot_position: 9 },
'457': { a: 51, slot_position: 0 } };

inventory_slots = 30;
used_slots = [];
for(a in items){
if(items[a].slot_position > 0){
used_slots.push(items[a].slot_position);
}
}


console.log(used_slots);


See on jsfiddle: http://jsfiddle.net/sf71L5jq/6/



So, a user has 30 available inventory slots. And the above console logs this array:



[13, 2, 12, 3, 17, 7, 11, 15, 1, 14, 8, 16, 5, 6, 20, 4, 19, 9]



How would I go about finding that first open number (slot)? In this case, it should be 10. But how to accomplish this dynamically?



Edit: @Tim Lewis's idea is here: http://jsfiddle.net/sf71L5jq/8/ But it doesn't catch the correct number. (NOTE: Not saying his idea is wrong, it's probably my code).



for(i=1; i < inventory_slots; i++){
if(used_slots[i] != i){
first_open = used_slots[i]; // Why is first_open assigned '2'?
break;
}
}


Answers

First of all, the values need to be sorted in numeric order:



used_slots.sort(sortNumber);

function sortNumber(a, b){
return a - b;
}


Next, loop through using a counter and find the first index that doesn't match your counter:



for(i = 0; i < inventory_slots; i++){
if(used_slots[i] != i+1){
first_open = i+1;
break;
}
}
console.log(first_open); // 10


In this case, the first open slot is 10. Also note, index starts at 0, not 1, but slot numbers start at 1, which explains the comparison if(used_slots[i] != i+1) and assignment first_open = i+1;



Answers

Assuming used slot values always start at 1, sort the array, then loop through it and compare the current increment with the current value. For example, after sorting your example array above, it would look like this:



[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 19, 20]



As you loop through, starting at 1, compare the increment variable with the current value:



if (used_slots[i] != (i+1)) {
// You have found the open slot
}


Full code would look like:



(See: arr.sort() does not sort integers correctly for sorting integers)



function sortNumber(a,b) {
return a - b;
}
used_slots.sort(sortNumber);

for (i = 0; i < used_slots.length; i++) {
if (used_slots[i] != (i+1)) {
// You have found the open slot
}
}


Answers

Try something like



for(var i=1; used_slots.indexOf(i) > 0; ++i);
i; // 10


But note indexOf will be slow for huge arrays. Better use searches in a hash table.



var hashTable = Object.create(null);
for(p in items) if(items.hasOwnProperty(p))
hashTable[items[p].slot_position] = true;
for(var i=1; hashTable[i]; ++i);
i; // 10




how to retrieve NSURLRequest's HTTPBody params to Dictionary: [NSObject: AnyObject] in Swift

I am attempting to convert a NSURLRequest's HTTPBody from NSData to a Dictionary, so that access it's parameters and run a check.



 var parameters: [NSObject: AnyObject?] = [
"method": "foo",
]
var urlRequestString = "www.foobar.com/api/aMethod"
var urlRequest = AFOAuth2Manager().requestSerializer.requestWithMethod("POST",
URLString:urlRequestString ,
parameters: postParameters,
error: nil)


in another method, I am attempting to run a check on the urlRequest being constructed above to ensure that the "method" in the NSURLRequest contain's the right value "foo".



What i need is to convert the HTTPBody to a Dictionary ( [NSObject: AnyObject])
so that i can check to see if the "method" parameter contains the value I need.



How can i achieve this?



Answers

Try this:



func queryDictionaryForQueryString(query: String) -> Dictionary<String, String> {
var dictionary = [String: String]()

for keyValueString in query.componentsSeparatedByString("&") {
var parts = keyValueString.componentsSeparatedByString("=")
if parts.count < 2 { continue; }

var key = parts[0].stringByRemovingPercentEncoding!
var value = parts[1].stringByRemovingPercentEncoding!

dictionary[key] = value
}

return dictionary
}


then you can



let httpBody = urlRequest.HTTPBody
let httpBodyString = NSString(data: httpBody!, encoding: NSUTF8StringEncoding) as! String
let queryDictionary = queryDictionaryForQueryString(httpBodyString)
println(queryDictionary["method"])




↑このページのトップヘ