Related
In order to find the largest dataset among others and concatenate them, I'm sorting them by their lengths.
Now, I'd like to concatenate them, but I'd need to turn these strings into the variable name, so that I can iterate through each of these datasets, concatenating them.
I've seen that window[] is used in JavaScript, but what about in GAS?
function concatenateData() {
let dataSizes = [];
//Separated datasets
let finalFabricData = [
["A", "C", 3],
["S", "R", 4],
["C", "O", 3]
];
dataSizes.push('finalFabricData', finalFabricData.length);
let finalDecorationData = [
["T", "D", 3],
["F", "F", 4],
["G", "O", 3]
];;
dataSizes.push('finalDecorationData', finalDecorationData.length)
let finalHtData = [
["A", "C", 3],
["S", "R", 4],
["K", "O", 3]
];
dataSizes.push('finalHtData', finalHtData.length);
let finalOrderData = [
["Z", "C", 3]
];
dataSizes.push('finalOrderData', finalOrderData.length);
//Attempt to grab the variable names, but they come as strings
let data1 = dataSizes[0][0];
let data2 = dataSizes[1][0];
let data3 = dataSizes[2][0];
let data4 = dataSizes[3][0];
//Attempt to concatenate them, but data1 is not iterable
let finalDataset = [];
data1.forEach(function(row, i) {
row = row.concat(data2[i], data3[i], data4[i]);
finalDataset.push(row)
});
}
Exected Result
let res = [
["A", "C", 3, "T", "D", 3, "A", "C", 3, "Z", "C", 3],
["S", "R", 4, "F", "F", 4, "S", "R", 4, "", "", ""],
["C", "O", 3, "G", "O", 3, "K", "O", 3, "", "", ""]
];
In your situation, how about the following sample script?
Sample script:
// These are from your script.
let finalFabricData = [
["A", "C", 3],
["S", "R", 4],
["C", "O", 3]
];
let finalDecorationData = [
["T", "D", 3],
["F", "F", 4],
["G", "O", 3]
];;
let finalHtData = [
["A", "C", 3],
["S", "R", 4],
["K", "O", 3]
];
let finalOrderData = [
["Z", "C", 3]
];
// I modified the below script.
const arrays = [finalFabricData, finalDecorationData, finalHtData, finalOrderData];
const res = arrays[0].map((_, c) => arrays.flatMap(r => r[c] || Array(3).fill("")));
console.log(res)
When this script is run, your expected values are retrieved.
References:
map()
flatMap()
I have data in JSON format, the sample is given below. I want to calculate the min and max range for the values inside the variable i.e. align_X, align_Y, align_Z.
{"id": 0, "variable": {"align_X": 41, "align_Y": 51, "align_Z": 80}}
{"id": 1, "variable": {"align_X": 0}}
{"id": 2, "variable": {"align_Y": 1, "align_Z": 0}}
Desired output is:
"align_X": [
0.0,
41.0
],
"align_Y": [
1.0,
51.0
],
"align_Z": [
0.0,
80.0
]
Any help is appropriated.
Thank you
Can you try this
var test = [{
"id": 0,
"variable": {
"align_X": 41,
"align_Y": 51,
"align_Z": 80
}
}, {
"id": 1,
"variable": {
"align_X": 0
}
}, {
"id": 2,
"variable": {
"align_Y": 1,
"align_Z": 0
}
}
]
var result = test.reduce((acc, cobj) => {
for (key in cobj.variable) {
if (acc[key]) {
if(acc[key][0] > cobj.variable[key]){
if(!acc[key][1]){
acc[key][1] = acc[key][0];
}
acc[key][0] = parseFloat(cobj.variable[key]).toFixed(2)
} else if(acc[key][1] == undefined || acc[key][1] < cobj.variable[key]){
acc[key][1] = parseFloat(cobj.variable[key]).toFixed(2)
}
}
else {
acc[key] = [];
acc[key].push(parseFloat(cobj.variable[key]).toFixed(2))
}
}
return acc;
}, []);
console.log(result);
My solution
#Your input
d = [{"id": 0, "variable": {"align_X": 41, "align_Y": 51, "align_Z": 80}},
{"id": 1, "variable": {"align_X": 0}},
{"id": 2, "variable": {"align_Y": 1, "align_Z": 0}}
]
#To store result float(-inf) smallest number in python & float(inf) is largest
output = {
"align_X" : [float('inf'),float('-inf')],
"align_Y" : [float('inf'),float('-inf')],
"align_Z" : [float('inf'),float('-inf')]
}
for item in d:
for each in output.keys():
try:
if item['variable'][each]<output[each][0]:
output[each][0] = item['variable'][each]
if item['variable'][each]>output[each][1]:
output[each][1] = item['variable'][each]
except:
continue
print(output)
I'm trying to add a "#" at the beginning to each key of a Json object (got it from RabbitMQ api calls)
here is my attempt :
#!/bin/python
# Libraries import
import requests
import json
import sys
import os
# Define URLs
overview="/api/overview"
nodes="/api/nodes"
queues="/api/queues"
# Get credentials from file
with open('/credentials') as json_file:
data = json.load(json_file)
user = data['user']
passwd = data['pass']
# Test which URL we want to call
if ''.join(sys.argv[1]) == "overview":
commande=overview
if ''.join(sys.argv[1]) == "queues":
commande=queues
if ''.join(sys.argv[1]) == "nodes":
commande=nodes
def append(mydict):
return dict(map(lambda (key, value): ("#"+str(key), value), mydict.items()))
def transform(multileveldict):
new = append(multileveldict)
for key, value in new.items():
if isinstance(value, dict):
new[key] = transform(value)
return new
def upper_keys(x):
if isinstance(x, list):
return [upper_keys(v) for v in x]
elif isinstance(x, dict):
return dict((k.upper(), upper_keys(v)) for k, v in x.iteritems())
else:
return x
# Main
response = requests.get("http://localhost:15672" + commande, auth=(user, passwd))
if(response.ok):
json_data = json.loads(response.content)
json = json.dumps(upper_keys(json_data), indent=4)
print(json)
Here is the JSON that I get in "response.content" :
[
{
"NODE": "rabbit#server567",
"EXCLUSIVE": false,
"NAME": "test-01",
"SYNCHRONISED_SLAVE_NODES": [],
"SLAVE_NODES": [],
"AUTO_DELETE": false,
"VHOST": "/",
"ARGUMENTS": {},
"TYPE": "classic",
"DURABLE": false
},
{
"NODE": "rabbit#server567",
"EXCLUSIVE": false,
"NAME": "test-02",
"SYNCHRONISED_SLAVE_NODES": [],
"SLAVE_NODES": [],
"AUTO_DELETE": false,
"VHOST": "/",
"ARGUMENTS": {},
"TYPE": "classic",
"DURABLE": false
},
{
"NODE": "rabbit#server567",
"EXCLUSIVE": false,
"NAME": "test-03",
"SYNCHRONISED_SLAVE_NODES": [],
"SLAVE_NODES": [],
"AUTO_DELETE": false,
"VHOST": "/",
"ARGUMENTS": {},
"TYPE": "classic",
"DURABLE": false
},
{
"MESSAGES_UNACKNOWLEDGED_RAM": 0,
"RECOVERABLE_SLAVES": null,
"CONSUMERS": 0,
"REDUCTIONS": 9700519,
"AUTO_DELETE": false,
"MESSAGE_BYTES_PAGED_OUT": 0,
"MESSAGE_BYTES_UNACKNOWLEDGED": 0,
"REDUCTIONS_DETAILS": {
"RATE": 0.0
},
"MESSAGE_BYTES": 0,
"MESSAGES_UNACKNOWLEDGED": 0,
"CONSUMER_UTILISATION": null,
"EXCLUSIVE": false,
"VHOST": "/",
"GARBAGE_COLLECTION": {
"MAX_HEAP_SIZE": 0,
"MIN_HEAP_SIZE": 233,
"FULLSWEEP_AFTER": 65535,
"MINOR_GCS": 15635,
"MIN_BIN_VHEAP_SIZE": 46422
},
"MESSAGES_DETAILS": {
"RATE": 0.0
},
"SLAVE_NODES": [
"rabbit#server567"
],
"MESSAGE_BYTES_PERSISTENT": 0,
"POLICY": "ha-all",
"MESSAGES_PAGED_OUT": 0,
"NODE": "rabbit#server566",
"HEAD_MESSAGE_TIMESTAMP": null,
"DURABLE": false,
"MESSAGES_READY_RAM": 0,
"STATE": "running",
"ARGUMENTS": {},
"EFFECTIVE_POLICY_DEFINITION": {
"HA-MODE": "all"
},
"MESSAGES_READY": 0,
"MESSAGES_RAM": 0,
"MESSAGE_BYTES_READY": 0,
"SINGLE_ACTIVE_CONSUMER_TAG": null,
"NAME": "test-04",
"MESSAGES_PERSISTENT": 0,
"BACKING_QUEUE_STATUS": {
"MIRROR_SENDERS": 0,
"Q1": 0,
"Q3": 0,
"Q2": 0,
"Q4": 0,
"AVG_ACK_EGRESS_RATE": 0.0,
"MIRROR_SEEN": 0,
"LEN": 0,
"TARGET_RAM_COUNT": "infinity",
"MODE": "default",
"NEXT_SEQ_ID": 0,
"DELTA": [
"delta",
"undefined",
0,
0,
"undefined"
],
"AVG_ACK_INGRESS_RATE": 0.0,
"AVG_EGRESS_RATE": 0.0,
"AVG_INGRESS_RATE": 0.0
},
"MESSAGES": 0,
"IDLE_SINCE": "2020-10-16 13:50:50",
"OPERATOR_POLICY": null,
"SYNCHRONISED_SLAVE_NODES": [
"rabbit#server567"
],
"MEMORY": 10556,
"EXCLUSIVE_CONSUMER_TAG": null,
"MESSAGES_READY_DETAILS": {
"RATE": 0.0
},
"TYPE": "classic",
"MESSAGES_UNACKNOWLEDGED_DETAILS": {
"RATE": 0.0
},
"MESSAGE_BYTES_RAM": 0
}
]
Here, I made every key in uppercase and can display it has JSON but can't find anything to add this "#" to the beginning of each key
PS : I'm new to Python development
Thank you very much
Since you mentioned that you have successfully converted every keys in a dictionary into upper case keys, why don't you reuse the method and change the part where you do upper case into prepending "#"
# the one you provided
def upper_keys(x):
if isinstance(x, list):
return [upper_keys(v) for v in x]
elif isinstance(x, dict):
return dict((k.upper(), upper_keys(v)) for k, v in x.iteritems())
else:
return x
# the modified method
def prepend_hash_keys(x):
if isinstance(x, list):
return [prepend_hash_keys(v) for v in x]
elif isinstance(x, dict):
# this part from k.upper() to "#" + k
return dict(("#" + k, prepend_hash_keys(v)) for k, v in x.iteritems())
else:
return x
Your transform function actually works fine (for Python 2), you just forgot to actually call it! Instead, you call only upper_keys, but not transform:
json = json.dumps(upper_keys(json_data), indent=4) # where's transform?
If you use both one after the other (order does not matter) it should work:
json = {"nested": {"dict": {"with": {"lowercase": "keys"}}}}
print(transform(upper_keys(json)))
# {'#NESTED': {'#DICT': {'#WITH': {'#LOWERCASE': 'keys'}}}}
However, both transform and upper_keys can be simplified a lot using dictionary comprehensions (also available in Python 2), and you can combine both in one function:
def transform_upper(d):
if isinstance(d, dict):
return {"#" + k.upper(): transform_upper(v) for k, v in d.items()}
else:
return d
print(transform_upper(json))
# {'#NESTED': {'#DICT': {'#WITH': {'#LOWERCASE': 'keys'}}}}
From the look of it you already tried something like that in append() function.
If you modify that a bit to have something like this, it may do what you are looking for:
mydict = {
'name':1,
'surname':2
}
def append(mydict):
new_dict = {}
for key, val in mydict.items():
new_dict['#'+key]=val
return new_dict
print(append(mydict))
Suppose I have a JSON object like this:
{
"foo": true,
"bar": {
"baz": 1,
"qux": {
"msg": "hello world",
"wow": [null]
}
}
}
And I want to flatten it recursively to a single layer, with the keys merged with an underscore:
{
"foo": true,
"bar_baz": 1,
"baz_qux_msg": "hello world",
"baz_qux_wow": [null]
}
How can I do this with Circe?
(Note: this is another FAQ from the Circe Gitter channel.)
You can do this without too much pain in Circe with a recursive method:
import io.circe.Json
def flatten(combineKeys: (String, String) => String)(value: Json): Json = {
def flattenToFields(value: Json): Option[Iterable[(String, Json)]] =
value.asObject.map(
_.toIterable.flatMap {
case (k, v) => flattenToFields(v) match {
case None => List(k -> v)
case Some(fields) => fields.map {
case (innerK, innerV) => combineKeys(k, innerK) -> innerV
}
}
}
)
flattenToFields(value).fold(value)(Json.fromFields)
}
Here our internal flattenToFields method takes each JSON value and either returns None if it's a non-JSON object value, as a signal that that field doesn't need flattening, or a Some containing a sequence of flattened fields in the case of a JSON object.
If we have a JSON value like this:
val Right(doc) = io.circe.jawn.parse("""{
"foo": true,
"bar": {
"baz": 1,
"qux": {
"msg": "hello world",
"wow": [null]
}
}
}""")
We can verify that flatten does what we want like this:
scala> flatten(_ + "_" + _)(doc)
res1: io.circe.Json =
{
"foo" : true,
"bar_baz" : 1,
"bar_qux_msg" : "hello world",
"bar_qux_wow" : [
null
]
}
Note that flattenToFields is not tail recursive, and will overflow the stack for deeply-nested JSON objects, but probably not until you're several thousand levels deep, so it's unlikely to be an issue in practice. You could make it tail recursive without too much trouble, but at the expense of additional overhead for the common cases where you only have a few layers of nesting.
I propose a variation of the solution by Travis Brown. The variation concerns objects in the JSON lists, i.e. how to handle
{
"foo": true,
"bar": {
"baz": 1,
"qux": {
"msg": "hello world",
"wow": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]
}
}
}
One possible solution for recursively handling objects in lists is the following implementation, where the position in the list is taken as an additional key part
def flattenDeep(combineKeys: (String, String) => String)(value: Json): Json = {
def flattenToFields(value: Json): Option[Iterable[(String, Json)]] = {
value.fold(
jsonNull = None,
jsonNumber = _ => None,
jsonString = _ => None,
jsonBoolean = _ => None,
jsonObject = { obj =>
val fields = obj.toIterable.flatMap {
case (field, json) =>
flattenToFields(json).fold(Iterable(field -> json)) {
_.map {
case (innerField, innerJson) =>
combineKeys(field, innerField) -> innerJson
}
}
}
Some(fields)
},
jsonArray = { array =>
val fields = array.zipWithIndex.flatMap {
case (json, index) =>
flattenToFields(json).fold(Iterable(index.toString -> json)) {
_.map {
case (innerField, innerJson) =>
combineKeys(index.toString, innerField) -> innerJson
}
}
}
Some(fields)
}
)
}
flattenToFields(value).fold(value)(Json.fromFields)
}
With this implementation the above example is flattened to:
{
"foo" : true,
"bar_baz" : 1,
"bar_qux_msg" : "hello world",
"bar_qux_wow_0_x" : 1,
"bar_qux_wow_0_y" : 2,
"bar_qux_wow_1_x" : 3,
"bar_qux_wow_1_y" : 4
}
For even deeper nested structures one still gets a flat representation, e.g.
{
"foo": true,
"bar": {
"baz": 1,
"qux": {
"msg": "hello world",
"wow": [
{
"x": 1,
"y": 2
},
{
"x": 3,
"y": 4
}
],
"deeper": [
{
"alpha": {
"h": 12,
"m": 1
},
"beta": [ "a", "b", "c" ]
},
{
"alpha": {
"h": 21,
"m": 0
},
"beta": [ "z" ]
}
]
}
}
}
will be flattened into
{
"foo" : true,
"bar_baz" : 1,
"bar_qux_msg" : "hello world",
"bar_qux_wow_0_x" : 1,
"bar_qux_wow_0_y" : 2,
"bar_qux_wow_1_x" : 3,
"bar_qux_wow_1_y" : 4,
"bar_qux_deeper_0_alpha_h" : 12,
"bar_qux_deeper_0_alpha_m" : 1,
"bar_qux_deeper_0_beta_0" : "a",
"bar_qux_deeper_0_beta_1" : "b",
"bar_qux_deeper_0_beta_2" : "c",
"bar_qux_deeper_1_alpha_h" : 21,
"bar_qux_deeper_1_alpha_m" : 0,
"bar_qux_deeper_1_beta_0" : "z"
}
On TripAdvisor.com attraction pages, the link to the website of the attraction seems to be encrypted in some way. Here is an example:
<span class="taLnk hvrIE6" onclick="ta.trackEventOnPage('AttractionContactInfo',
'Website', 1755031, 1); ta.util.cookie.setPIDCookie(15190);
ta.call('ta.util.link.targetBlank', event, this
{'aHref':'LqMWJQiMnYQQoqnQQxGEcQQoqnQQbIIEJnISiCQQoqnQQeVsSVuWJQzZYUWJQpEcYGII26XombQQoqnQQQQoqnqgoqnQQQQoqnQQQQoqnQQQQoqnqgoqnQQQQoqnQQEVMIGVJIEV9pCyTptGiuQQoqnQQQQoqnxioqnQQQQoqnQQniaWJQzhY3mJnJUUJXomoAvoJJB', 'isAsdf':true})">
Website
</span>
How is this link made and what might be the reason for doing so?
The aHref value is an encrypted URL that can be decrypted using the TripAdvisor asdf() Javascript function. For example, using the Javascript console in Firefox, type the following while at www.tripadvisor.com:
console.log(asdf('encrypted URL'));
An example:
console.log(asdf('LqMWJQzZYUWJQpEcYGII26XombQQoqnQQQQoqnqgoqnQQQQoqnQQQQoqnQQQQoqnqgoqnQQQQoqnQQuuuQQoqnQQQQoqnxioqnQQQQoqnQQEitVuiiMqxQQoqnQQQQoqnxioqnQQQQoqnQQniaQQoqnQQQQoqnqgoqnQQQQoqnQQVCQQoqnQQQQoqnqgoqnQQQQoqnQQIGVQQoqnQQQQoqnqHoqnQQQQoqnQQnJEcgcVQQoqnQQQQoqnqHoqnQQQQoqnQQCVuQQoqnQQQQoqnqHoqnQQQQoqnQQgiE9QQoqnQQQQoqnqgoqnQQQQoqnQQMSCSCyQQoqnQQQQoqnqgoqnQQQQoqnQQHVaVcaJCtQQoqnQQQQoqnqHoqnQQQQoqnQQHJEWJQzhYUMo3JKHkmKnVmJVdUB'));
Gives the following (append to http://tripadvisor.com):
/ShowUrl-a_partnerKey.1-a_url.http%253A__5F____5F__2F__5F____5F____5F____5F__2F__5F____5F__www__5F____5F__2E__5F____5F__rosewoodhotels__5F____5F__2E__5F____5F__com__5F____5F__2F__5F____5F__en__5F____5F__2F__5F____5F__the__5F____5F__2D__5F____5F__carlyle__5F____5F__2D__5F____5F__new__5F____5F__2D__5F____5F__york__5F____5F__2F__5F____5F__dining__5F____5F__2F__5F____5F__bemelmans__5F____5F__2D__5F____5F__bar-a_urlKey.1d56a0b730ce3ae41.html
The source of the TripAdvisor asdf() function:
function asdf(d) {
var h = {
"": ["&", "=", "p", "6", "?", "H", "%", "B", ".com", "k", "9", ".html", "n", "M", "r", "www.", "h", "b", "t", "a", "0", "/", "d", "O", "j", "http://", "_", "L", "i", "f", "1", "e", "-", "2", ".", "N", "m", "A", "l", "4", "R", "C", "y", "S", "o", "+", "7", "I", "3", "c", "5", "u", 0, "T", "v", "s", "w", "8", "P", 0, "g", 0],
q: [0, "__3F__", 0, "Photos", 0, "https://", ".edu", "*", "Y", ">", 0, 0, 0, 0, 0, 0, "`", "__2D__", "X", "<", "slot", 0, "ShowUrl", "Owners", 0, "[", "q", 0, "MemberProfile", 0, "ShowUserReviews", '"', "Hotel", 0, 0, "Expedia", "Vacation", "Discount", 0, "UserReview", "Thumbnail", 0, "__2F__", "Inspiration", "V", "Map", ":", "#", 0, "F", "help", 0, 0, "Rental", 0, "Picture", 0, 0, 0, "hotels", 0, "ftp://"],
x: [0, 0, "J", 0, 0, "Z", 0, 0, 0, ";", 0, "Text", 0, "(", "x", "GenericAds", "U", 0, "careers", 0, 0, 0, "D", 0, "members", "Search", 0, 0, 0, "Post", 0, 0, 0, "Q", 0, "$", 0, "K", 0, "W", 0, "Reviews", 0, ",", "__2E__", 0, 0, 0, 0, 0, 0, 0, "{", "}", 0, "Cheap", ")", 0, 0, 0, "#", ".org"],
z: [0, "Hotels", 0, 0, "Icon", 0, 0, 0, 0, ".net", 0, 0, "z", 0, 0, "pages", 0, "geo", 0, 0, 0, "cnt", "~", 0, 0, "]", "|", 0, "tripadvisor", "Images", "BookingBuddy", 0, "Commerce", 0, 0, "partnerKey", 0, "area", 0, "Deals", "from", "\\", 0, "urlKey", 0, "'", 0, "WeatherUnderground", 0, "MemberSign", "Maps", 0, "matchID", "Packages", "E", "Amenities", "Travel", ".htm", 0, "!", "^", "G"]
};
var b = "";
for (var a = 0; a < d.length; a++) {
var j = d.charAt(a);
var f = j;
if (h[j] && a + 1 < d.length) {
a++;
f += d.charAt(a)
} else {
j = ""
}
var g = getOffset(d.charCodeAt(a));
if (g < 0 || typeof h[j][g] == "String") {
b += f
} else {
b += h[j][g]
}
}
return b}
And the source of the getOffset() function referred to from asdf():
function getOffset(a) {
if (a >= 97 && a <= 122) {
return a - 61
}
if (a >= 65 && a <= 90) {
return a - 55
}
if (a >= 48 && a <= 71) {
return a - 48
}
return -1}
It could possibly be done to prevent screen scrapers and robots from automatically generating traffic to other sites.
Some server side code generated this and it's used for tracking, statistics and setting some cookie values etc.
Trip advisor will be able to determine what links were clicked and also share this information with the attraction (i.e. 50 people accessed your website from the Trip Advisor website etc)
Hope it's useful