问:
Detect the next line in flex box containing div
I need to add the vertical line splitter between the div. But the div which is present at the end of the line should not contain the splitter. The div will be placed dynamically.

https://stackblitz.com/edit/angular-ivy-lxhcuu?file=src%2Fapp%2Fapp.component.css

document.addEventListener('DOMContentLoaded', () => {
  const parent = document.querySelector(".parent");
  const node = parent.firstElementChild;
  for (let i = 1; i < 30; i++) {
    parent.appendChild(node.cloneNode(true));
  }
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>p {
  font-family: Lato;
}

.parent {
  display: flex;
  flex-flow: wrap;
}

.paddingDta {
  padding: 5px;
}

.divider {
  border-left: 1px solid red;
}

.dividerPadding {
  margin: 2px;
}</code>```

      {{ data }}

```

答: You can use let isLast = last in ngFor and send it as a parameter to the component.</p>

Body:
I need to add the vertical line splitter between the div. But the div which is present at the end of the line should not contain the splitter. The div will be placed dynamically.

https://stackblitz.com/edit/angular-ivy-lxhcuu?file=src%2Fapp%2Fapp.component.css

document.addEventListener('DOMContentLoaded', () => {
  const parent = document.querySelector(".parent");
  const node = parent.firstElementChild;
  for (let i = 1; i < 30; i++) {
    parent.appendChild(node.cloneNode(true));
  }
});

p {
  font-family: Lato;
}

.parent {
  display: flex;
  flex-flow: wrap;
}

.paddingDta {
  padding: 5px;
}

.divider {
  border-left: 1px solid red;
}

.dividerPadding {
  margin: 2px;
}

      {{ data }}


来源: stackexchange

问:
How to filter an associative arrays using array of keys in PHP?
I have an associative arrays and an array of keys.

```<code>$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');
</code>```

How I build an associative array from all element of $A where the key is in $B?
For the example above, the answer should be

```<code>$C = array('a'=>'book', 'b'=>'pencil');
</code>```

答:
To my immense surprise, the foreach loop method is faster.

The following quick benchmark script gives me results:
array_intersect_key: 0.76424908638
foreach loop: 0.6393928527832

```<code>$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');

$start = microtime(true);
for ($i = 0 ; $i < 1000000; $i++) {
$c = array_intersect_key($A,array_flip($B));
}

$t1 = microtime(true);

for ($i = 0; $i < 1000000; $i++) {
$C = array();
    foreach ($B as $bval) {
          // If the $B key exists in $A, add it to $C
          if (isset($A[$bval])) $C[$bval] = $A[$bval];
    }
}

$t2 = microtime(true);
echo "array_intersect_key: " . ($t1 - $start), "\n";
echo "foreach loop: " . ($t2 - $t1), "\n";
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have an associative arrays and an array of keys.

$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');

How I build an associative array from all element of $A where the key is in $B?
For the example above, the answer should be

$C = array('a'=>'book', 'b'=>'pencil');

Body:
To my immense surprise, the foreach loop method is faster.

The following quick benchmark script gives me results:
array_intersect_key: 0.76424908638
foreach loop: 0.6393928527832

$A = array('a'=>'book', 'b'=>'pencil', 'c'=>'pen');
$B = array('a', 'b');

$start = microtime(true);
for ($i = 0 ; $i < 1000000; $i++) {
$c = array_intersect_key($A,array_flip($B));
}

$t1 = microtime(true);

for ($i = 0; $i < 1000000; $i++) {
$C = array();
    foreach ($B as $bval) {
          // If the $B key exists in $A, add it to $C
          if (isset($A[$bval])) $C[$bval] = $A[$bval];
    }
}

$t2 = microtime(true);
echo "array_intersect_key: " . ($t1 - $start), "\n";
echo "foreach loop: " . ($t2 - $t1), "\n";


问:
Excel Custom Ribbon Separators
I was looking for a way to insert vertical separators into a custom ribbon in Excel 2010, which seems to be problematic for everyone.</p>

答:
Here goes.. This applies to Excel 2010 on.

Enter the 'Customize Ribbon' window. Create a new tab, (this creates a blank custom ribbon), and also creates a default group within the tab, which you can rename, and add buttons/macros to.

Make sure your new tab is selected in the 'Customize Ribbon' window.

Add another group or maybe more, (I have 4 groups in my ribbon)

Insert your buttons/macros into each of these groups

Click 'OK' and voila, you now have vertical separators.

Export the customizations using the 'Import/Export' button at the bottom of the window, to the default file name ('Excel Customizations.exportedUI'), this is an XML file.

Edit this file with a text editor, look for the phrase 'autoScale="true" (there is one for each group), this will determine if your buttons are large or small, if this is set to true then its possible some buttons will be large and some small, change it to 'autoScale="false" to show small buttons.

Import your file back into the 'Customize Ribbon' window, click 'OK' to overwrite any existing customizations.

By default, ribbon groups are separated by a "vertical separator", you can have one or more buttons/macros within each group, evry group will have its own label across the bottom. It seems like everyone is trying to put all their buttons/macros into one group within their custom tab ribbon which is why they can't insert separators individually. This is the ONLY way you can have separators in your custom ribbon.

ContentLicense: CC BY-SA 4.0

Title: Excel Custom Ribbon Separators


问:
SQL determine business days passed since beginning of month using calendar table
I have a calendar table with all dates and a column indicating whether its a business day.

For example

Date
Business_Day

1/1/2021
False

1/2/2021
False

1/3/2021
True

...
I have another table with dates and would like to determine how many business days have elapsed since the beginning of that month.
For example:

Date
Business_Days_Passed

1/1/2022
0

1/2/2022
0

1/3/2022
1

1/4/2022
2

1/15/2022
10

2/2/2022
2

2/11/2022
9

2/12/2022
9

Is there a way to do this using standard sql?  I was thinking of creating some kind of UDF but there may be an easier way?  This using snowflake so there is access to all common date functions and window/udf functions

答:
try this with the single, table you can create a view</p>
```<code>create or replace table bus_day as
SELECT column1  Date, column2   Business_Day  from values
('1/1/2021',    'False'),
('1/2/2021',    'False'),
('1/3/2021',    'True'),
('1/4/2021',    'True'),
('1/5/2021',    'True'),
('1/6/2021',    'True'),
('1/7/2021',    'True'),
('2/1/2021',    'True'),
('2/2/2021',    'True'),
('2/3/2021',    'True'),
('2/4/2021',    'True'),
('2/5/2021',    'False'),
('2/6/2021',    'False'),
('2/7/2021',    'True')
;

  SELECT DATE,FIRST_DAY_MONTH
 ,row_number() over (partition by month(to_date(Date,'mm/dd/yyyy')) order by date) as row_number
 ,count_if(business_day ='True') over (partition by month(to_date(Date,'mm/dd/yyyy'))   order by DATE ) count_days
FROM (
  select Date , DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')) frst_day,
  iff(to_date(Date,'mm/dd/yyyy') = DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')), 'Y', 'N') first_day_Month ,
  business_day from bus_day order by date
   );
</code>```

Body:
try this with the single, table you can create a view

create or replace table bus_day as
SELECT column1  Date, column2   Business_Day  from values
('1/1/2021',    'False'),
('1/2/2021',    'False'),
('1/3/2021',    'True'),
('1/4/2021',    'True'),
('1/5/2021',    'True'),
('1/6/2021',    'True'),
('1/7/2021',    'True'),
('2/1/2021',    'True'),
('2/2/2021',    'True'),
('2/3/2021',    'True'),
('2/4/2021',    'True'),
('2/5/2021',    'False'),
('2/6/2021',    'False'),
('2/7/2021',    'True')
;

  SELECT DATE,FIRST_DAY_MONTH
 ,row_number() over (partition by month(to_date(Date,'mm/dd/yyyy')) order by date) as row_number
 ,count_if(business_day ='True') over (partition by month(to_date(Date,'mm/dd/yyyy'))   order by DATE ) count_days
FROM (
  select Date , DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')) frst_day,
  iff(to_date(Date,'mm/dd/yyyy') = DATE_TRUNC('month',to_date(Date,'mm/dd/yyyy')), 'Y', 'N') first_day_Month ,
  business_day from bus_day order by date
   );


问:
How can I access Istio Authorization details in my target Service(For e.g. Flask code)
For Example I have enabled the mTLS in my istio service in STRICT mode. and I have authorization policy that have kind of source.principals rule check.

Now I want to access these rules details like source.principals and source.namespace after request is authenticated and authorized so that I can do more business login in my flask(python) service.

My python code looks like this:

```<code>from flask import Flask
app = Flask(__name__)

@app.route("/mutate-hook", methods=['POST'])
def mutate():
    source = request.headers.get('source')
    # I am expacting source to the source from this: https://istio-releases.github.io/v0.1/docs/reference/config/mixer/attribute-vocabulary.html
    print(source)
    request_json = request.get_json()
    # I am expacting source to the source from this: https://istio-releases.github.io/v0.1/docs/reference/config/mixer/attribute-vocabulary.html
    request_source = request_json.get('source')
    print(request_source["principal"], request_source['namespace'])

</code>```

答: You can use X-Forwarded-Client-Cert header added by envoy, it contains the service account name of the sender like cluster.local/ns/default/sa/senderServiceAccountName from which you can find both the namespace and the deployment (if you used a separate service account for each of your deployments) of the sender.

Body:
For Example I have enabled the mTLS in my istio service in STRICT mode. and I have authorization policy that have kind of source.principals rule check.

Now I want to access these rules details like source.principals and source.namespace after request is authenticated and authorized so that I can do more business login in my flask(python) service.

My python code looks like this:

from flask import Flask
app = Flask(__name__)

@app.route("/mutate-hook", methods=['POST'])
def mutate():
    source = request.headers.get('source')
    # I am expacting source to the source from this: https://istio-releases.github.io/v0.1/docs/reference/config/mixer/attribute-vocabulary.html
    print(source)
    request_json = request.get_json()
    # I am expacting source to the source from this: https://istio-releases.github.io/v0.1/docs/reference/config/mixer/attribute-vocabulary.html
    request_source = request_json.get('source')
    print(request_source["principal"], request_source['namespace'])


问:
One-hot vs Grouping for Feature Engineering
**note I don't have 10 rep yet so I can't post images

Working with the Adult Census (goal is to predict which observed people will have an annual income greater than $50k/year) dataset for some ML practice and had a question for feature engineering...

The dataset has columns, of which 8 are categorical (workclass, education (dropped because integer education.num exists), marital.status, occupation, relationship, race, sex, native.country, and income)

these

In doing analysis, I first changed income to 1 for >$50K/year and 0 for <$50K/year.

```<code>data['income'] = data['income'].replace({'<=50K':0, '>50K' :1})
</code>```

However, when looking at the other variables, I needed some guidance/advice on how to approach them. For example, the 'workclass' column

```<code>plt.figure(figsize = (15,5))
sns.barplot(x = data['workclass'], y = data['income'])
plt.xlabel('Working Class')
plt.ylabel('Likelihood of income >= 50K')
plt.show()
</code>```

workclass

My first idea was to use one-hot encoding, however, like workclass, native.country, race,marital.status, and occupation are all unordered. This would create nearly 100 columns.

My next idea was to manually group them based on the probability of a certain column value having an income >$50K, picked based on plots like the one below

Martital.Status

Going by this, my inclination for each column would be

Column
Feature Engineering Decision

workclass
drop

marital.status
Group (married+present = 1, not married/estranged = 0

occupation
Group (white collar jobs (exec,prof,tech,sales) = 1, blue collar (all else) = 0

race
Unsure, only 5 variables so could one-hot or group by white vs non-white?

relationship
Group (Husband or Wife = 1, No marital relationship = 0

sex
One-hot, or Male = 1, Female = 0, Unsure need input

native.country
Tons of variables, I think Group by US vs non-US makes most sense

Here is a link to the full jupyter notebook with graphs for all categorical variables. So, can you help me decide if this is the right way to feature engineer the columns in my dataset?

答:
Although Adult Census is a classic toy dataset, I can't recall all the details so my answer may not be as informative as you expect. Still, I love everything about your decisions except maybe this idea:

My next idea was to manually group them based on the probability of a certain column value having an income >$50K, picked based on plots like the one below

Since your goal is to build a model that predicts income status for unobserved individuals, associating your categories directly with target will likely lead to overfitting; in test data, the distributions of categories can differ from those in training data. However, it does not mean that you shouldn't consider target classes at all. Indeed, try calculating probabilities on subsamples of your category columns or adding noise to the obtained probabilities. See category_encoders package for inspiration. Good luck!

P.S. Are workclass and education.num really identical?

Body:
**note I don't have 10 rep yet so I can't post images

Working with the Adult Census (goal is to predict which observed people will have an annual income greater than $50k/year) dataset for some ML practice and had a question for feature engineering...

The dataset has columns, of which 8 are categorical (workclass, education (dropped because integer education.num exists), marital.status, occupation, relationship, race, sex, native.country, and income)

these

In doing analysis, I first changed income to 1 for >$50K/year and 0 for <$50K/year.

data['income'] = data['income'].replace({'<=50K':0, '>50K' :1})

However, when looking at the other variables, I needed some guidance/advice on how to approach them. For example, the 'workclass' column

plt.figure(figsize = (15,5))
sns.barplot(x = data['workclass'], y = data['income'])
plt.xlabel('Working Class')
plt.ylabel('Likelihood of income >= 50K')
plt.show()

workclass

My first idea was to use one-hot encoding, however, like workclass, native.country, race,marital.status, and occupation are all unordered. This would create nearly 100 columns.

My next idea was to manually group them based on the probability of a certain column value having an income >$50K, picked based on plots like the one below

Martital.Status

Going by this, my inclination for each column would be

Column
Feature Engineering Decision

workclass
drop

marital.status
Group (married+present = 1, not married/estranged = 0

occupation
Group (white collar jobs (exec,prof,tech,sales) = 1, blue collar (all else) = 0

race
Unsure, only 5 variables so could one-hot or group by white vs non-white?

relationship
Group (Husband or Wife = 1, No marital relationship = 0

sex
One-hot, or Male = 1, Female = 0, Unsure need input

native.country
Tons of variables, I think Group by US vs non-US makes most sense

Here is a link to the full jupyter notebook with graphs for all categorical variables. So, can you help me decide if this is the right way to feature engineer the columns in my dataset?


问:
Maintaining message integrity
I have a message that I am passing to myself which will be subject to man-in-the-middle attacks.  Because of that, I am concerned about the integrity of the message being maintained between the time I send it, and the time that I receive it back.

It should be assumed that once I send the message to myself, no information about the message sent will be available to me in the future.  The message is completely self-contained.

To that end, I know that should hash the message contents and compare the hashes before I send the message, and after I send the message, if they differ, then the message has been tampered with.

Of course, if the man-in-the-middle knows that the hash is really just the hash of the message contents, as-is, then because the message is self-contained, he can just create new contents and apply the same hash algorithm to the contents.

The question is, to what lengths should I go to randomize the message contents when generating the hash?  When does it reach the point of diminishing returns?

In this scenario, I have a set of key/value pairs.  To that end, the steps that I know I HAVE to take are:

Add a salt to the message.  The salt is a secret to the rest of the world.  It gets attached to the contents of the message before hashing.

Order the key/value pairs in a consistent manner before generating the hash.

While not directly relevant, a timestamp is going to be added to the contents of each message before hashing, to prevent replay attacks.

These are the optional steps that I am considering:

Transforming the keys before I order them.  I've considered reversing them, then ordering by count/key.

Playing with the separators that separate key/value pairs (both for the separator for the key/value and the separator for the pair).

NOTE

Message privacy is not a requirement here, so I am not looking for encryption.  The values must be transmitted in plain-text.

Finally, what hashing algorithms should I avoid?

Specifics

I have an ASP.NET MVC site which I have a controller which handles input validation and persistence.

If (based on a heuristic, it's not important which) the input is determined to be an automated spam attempt, a model of IDictionary<string, string> is created with the input values and a ViewResult is sent to a general CAPTCHA page.

In that view, in the form that contains the CAPTCHA control, the contents of the IDictionary<string, string> will be written out in hidden input fields, and the action of the form will be the same action that the contents were originally posted to.  This way, MVC can pick up the values when the form is resubmitted.

It's because of this I can't encrypt the key/value pairs (or maybe I can and should, tell me why and how!).

Of course, I need to add one more value, which contains the hashed message contents.  If that value is there, then the controller will check to see that the message integrity is maintained, and allow the input to be persisted if it has.

Solution

I've opted to go with the SignedCms class in the System.Security.Cyrptography.Pkcs namespace, which represents the signging and verifying of CMS/PKCS #7 messages.

To elaborate, I've created a self-issued certificate with MAKECERT.EXE and then in my code, I use the example here to digitally sign the data:

http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx

Now, it should be a matter of keeping the password on the exported private key secure, as well as security on the server, which makes it less about programming.

I'll have to add an extra key for the timestamp for replay attacks, but that won't be too hard.

The answer goes to Kalium, not for his initial post, but for his follow up comments which pointed the way to digital signatures, and eventually my discovery of how to utilize them in .NET.

Thanks to everyone who contributed.

答: You want a Digitally Signed message.  Using GPG you can sign the message without encrypting it.  But no one will be able to tamper with it, because they can't generate the hash - only you can because the hash uses your private key.

OwnerDisplayName: casperOne

ContentLicense: CC BY-SA 2.5

Title: Maintaining message integrity

LastEditorDisplayName: casperOne

OwnerDisplayName: Tom Ritter


问:
Codeigniter Ocular and Form Validation
New to CodeIgniter and new to Ocular so bear with me.

I used to code in the following way when running form validation (where the index() method contains the form loading code):

```<code>if ($this->form_validation->run() == FALSE)
{
    $this->index();
}
else
{
    $this->load->view('view_name', $data);
}
</code>```

However I'm now trying to use the Ocular Template Library and the above code no longer works see example below:

```<code>if ($this->form_validation->run() == FALSE)
{
    $this->index();
}
else
{
    $this->template->set($data);
    $this->template->render();
}
</code>```

The above code does not run through the index method as it used to without Ocular and I was wondering what the best practice is to correct this or even if my previous code was best practice?

Regards,
Numan1617

答:
Sometimes it's hard to determine best practice with Codeigniter because it's convention-less nature, so all I can really tell you is how I've found best in my experience...

I assume you're form view is being served up via index() and then you're submitting your form to this (seperate) controller function that validates and processes the form data, and re-displays the view with errors if there was a problem...

I would clean this up by consolidating it all into a single function...

```<code>public function form()
{
    //if this is a post request
    if ($_POST)
    {
        //check the validation
        if ($this->form_validation->run())
        {
            //process it
            //and then redirect if you want to send to a "success" page
            redirect('uri/to/success');
        }
        else
        {
            //load up $data values to re-display form
        }
    }

    //load up any $data values needed for standard view
    $this->load->view('view', $data);
    // or $this->template stuff...

}
</code>```

It always seemed to me to be a bad route to go down calling controller functions internally, ex. $this->index()

Title: Codeigniter Ocular and Form Validation

Body:
New to CodeIgniter and new to Ocular so bear with me.

I used to code in the following way when running form validation (where the index() method contains the form loading code):

if ($this->form_validation->run() == FALSE)
{
    $this->index();
}
else
{
    $this->load->view('view_name', $data);
}

However I'm now trying to use the Ocular Template Library and the above code no longer works see example below:

if ($this->form_validation->run() == FALSE)
{
    $this->index();
}
else
{
    $this->template->set($data);
    $this->template->render();
}

The above code does not run through the index method as it used to without Ocular and I was wondering what the best practice is to correct this or even if my previous code was best practice?

Regards,
Numan1617

Body:
Sometimes it's hard to determine best practice with Codeigniter because it's convention-less nature, so all I can really tell you is how I've found best in my experience...

I assume you're form view is being served up via index() and then you're submitting your form to this (seperate) controller function that validates and processes the form data, and re-displays the view with errors if there was a problem...

I would clean this up by consolidating it all into a single function...

public function form()
{
    //if this is a post request
    if ($_POST)
    {
        //check the validation
        if ($this->form_validation->run())
        {
            //process it
            //and then redirect if you want to send to a "success" page
            redirect('uri/to/success');
        }
        else
        {
            //load up $data values to re-display form
        }
    }

    //load up any $data values needed for standard view
    $this->load->view('view', $data);
    // or $this->template stuff...

}

It always seemed to me to be a bad route to go down calling controller functions internally, ex. $this->index()


问:
Turning based on joystick axis degree with Unity's new Input System
Here is my code:

```<code>void Update()
{
    if (playerControls.Player.Jump.triggered)
    {
        Jump();
    }

    if (playerControls.Player.TurnLeft.triggered)
    {
        transform.Rotate(Vector3.down * rotateSpeed * Time.deltaTime);
    }

    Vector2 move = playerControls.Player.Move.ReadValue<Vector2>();

    Debug.Log(move);

    if (move.x < 0)
    {
        Debug.Log(move);
        transform.Rotate(Vector3.down * rotateSpeed * Mathf.Abs(move.x) * Time.deltaTime);
    }
    else if (move.x > 0)
    {
        Debug.Log(move);
        transform.Rotate(Vector3.up * rotateSpeed * Mathf.Abs(move.x) * Time.deltaTime);
    }
}
</code>```

This mostly works, but I'm trying to repeat the rotate action while the button is held, and using IsPressed instead of triggered gives me the following error:

Cannot convert method group 'IsPressed' to non-delegate type 'bool'.
Did you intend to invoke this method?

I can solve this by creating a Boolean that changes on trigger/release, but I also want to use move.x to detect the controller's X axis to be able to turn slower based on how far the joystick is pushed to the left or right.

How can I repeat the action while a button is pressed down, and in the case of a controller being used, how can I get the x-axis value of the joystick to control the speed of rotation?

答: IsPressed() is a method. You want to use isPressed property. Notice small 'i'.

Body:
Here is my code:

void Update()
{
    if (playerControls.Player.Jump.triggered)
    {
        Jump();
    }

    if (playerControls.Player.TurnLeft.triggered)
    {
        transform.Rotate(Vector3.down * rotateSpeed * Time.deltaTime);
    }

    Vector2 move = playerControls.Player.Move.ReadValue<Vector2>();

    Debug.Log(move);

    if (move.x < 0)
    {
        Debug.Log(move);
        transform.Rotate(Vector3.down * rotateSpeed * Mathf.Abs(move.x) * Time.deltaTime);
    }
    else if (move.x > 0)
    {
        Debug.Log(move);
        transform.Rotate(Vector3.up * rotateSpeed * Mathf.Abs(move.x) * Time.deltaTime);
    }
}

This mostly works, but I'm trying to repeat the rotate action while the button is held, and using IsPressed instead of triggered gives me the following error:

Cannot convert method group 'IsPressed' to non-delegate type 'bool'.
Did you intend to invoke this method?

I can solve this by creating a Boolean that changes on trigger/release, but I also want to use move.x to detect the controller's X axis to be able to turn slower based on how far the joystick is pushed to the left or right.

How can I repeat the action while a button is pressed down, and in the case of a controller being used, how can I get the x-axis value of the joystick to control the speed of rotation?


问:
create new column on conditions python
I have a ref table df_ref like this:

```<code>col1 col2 ref
a    b    a,b
c    d    c,d
</code>```

I need to create a new column in another table based on ref table.The table like this:

```<code>col1 col2
a    b
a    NULL
NULL b
a    NULL
a    NULL
c    d
c    NULL
NULL NULL
</code>```

The output table df_org looks like:

```<code>col1  col2   ref
a     b      a,b
a     NULL   a,b
NULL  b      a,b
a     NULL   a,b
a     NULL   a,b
c     d      c,d
c     NULL   c,d
NULL  NULL   NULL
</code>```

If any column value in col1 and col2 can find in ref table, it will use the ref col in ref table. If col1 and col2 are NULL, So they cannot find anything in ref table, just return NULL. I use this code, but it doesn't work.

```<code>df_org['ref']=np.where(((df_org['col1'].isin(df_ref['ref'])) |
         (df_org['col2'].isin(df_ref['ref']))
          ), df_ref['ref'], 'NULL')
</code>```

ValueError: operands could not be broadcast together with shapes

答:
You want to perform two merges and combine them:

```<code>df_org = (
 df.merge(df_ref.drop('col2', axis=1), on='col1', how='left')
   .combine_first(df.merge(df_ref.drop('col1', axis=1), on='col2', how='left'))
)
</code>```

output:

```<code>  col1 col2  ref
0    a    b  a,b
1    a  NaN  a,b
2  NaN    b  a,b
3    a  NaN  a,b
4    a  NaN  a,b
5    c    d  c,d
6    c  NaN  c,d
7  NaN  NaN  NaN
</code>```

Title: create new column on conditions python

Body:
I have a ref table df_ref like this:

col1 col2 ref
a    b    a,b
c    d    c,d

I need to create a new column in another table based on ref table.The table like this:

col1 col2
a    b
a    NULL
NULL b
a    NULL
a    NULL
c    d
c    NULL
NULL NULL

The output table df_org looks like:

col1  col2   ref
a     b      a,b
a     NULL   a,b
NULL  b      a,b
a     NULL   a,b
a     NULL   a,b
c     d      c,d
c     NULL   c,d
NULL  NULL   NULL

If any column value in col1 and col2 can find in ref table, it will use the ref col in ref table. If col1 and col2 are NULL, So they cannot find anything in ref table, just return NULL. I use this code, but it doesn't work.

df_org['ref']=np.where(((df_org['col1'].isin(df_ref['ref'])) |
         (df_org['col2'].isin(df_ref['ref']))
          ), df_ref['ref'], 'NULL')

ValueError: operands could not be broadcast together with shapes

Body:
You want to perform two merges and combine them:

df_org = (
 df.merge(df_ref.drop('col2', axis=1), on='col1', how='left')
   .combine_first(df.merge(df_ref.drop('col1', axis=1), on='col2', how='left'))
)

output:

  col1 col2  ref
0    a    b  a,b
1    a  NaN  a,b
2  NaN    b  a,b
3    a  NaN  a,b
4    a  NaN  a,b
5    c    d  c,d
6    c  NaN  c,d
7  NaN  NaN  NaN


问:
How do I send a message to a specific channel on a specific message in node.js

client.on('message', function(message) {
 if (message.content === 'msg-1')
client.channels.cache.get('Channel_id').send('msg-2')
 }
});```

How to make the code send a specific message on a specific message in node.js I tried the code above but it don't work this is my first code in node.js so there could be silly mistakes thanks in advance for the answer

答:
You put an additional quirly bracket

So the code needs to be like this:

client.on('message', function(message) {
 if (message.content === 'msg-1')
      client.channels.cache.get('Channel_id').send('msg-2')
});```

Body:
client.on('message', function(message) {
 if (message.content === 'msg-1')
client.channels.cache.get('Channel_id').send('msg-2')
 }
});

How to make the code send a specific message on a specific message in node.js I tried the code above but it don't work this is my first code in node.js so there could be silly mistakes thanks in advance for the answer


问:
MySQL command is not found in M1 Mac
as titled, my question is in my m1 Mac terminal, after successfully installing MySQL from the official page, I enter the mysql command, but it returns command not found.

I googled alot, and this is one of the solution i found:mysql command is not found in macOS

Per the instruction of the page, I found my path to my mysql already, it's /usr/local/mysql-8.0.27-macos11-arm64/bin,
I am now in my zshrc too, but i don't know how to put export PATH=$PATH:/usr/local/<my-path>/bin in to zshrc.

While there are so many lines of different settings in it, how do i specify this path is for mysql?
and where to put?

Thank you guys

答:
If not you using homebrew and have a manual installation of mysql:

```<code>vi ~/.zshrc
export PATH=${PATH}:/usr/local/mysql-8.0.28-macos11-x86_64/bin/
source ~/.zshrc
</code>```

note: replace /mysql-8.0.28-maos11-x86_64/ with whichever version of mysql is installed.

Title: MySQL command is not found in M1 Mac

Body:
If not you using homebrew and have a manual installation of mysql:

vi ~/.zshrc
export PATH=${PATH}:/usr/local/mysql-8.0.28-macos11-x86_64/bin/
source ~/.zshrc

note: replace /mysql-8.0.28-maos11-x86_64/ with whichever version of mysql is installed.


问:
Azure Active Directory B2C: How to query MS Graph to get a user's alternative security ID?
B2C uses an alternative security ID to uniquely identify users from social accounts.  We have a problem where a user enters credentials for a user, but somehow B2C authenticates the user as someone else.  I suspect the IDP is returning bad claims data or the alternative security IDs are the same.  How do I view the alternative security ID of a user in Active Directory?

I tried the following MS Graph query trying all the attributes I can think of (including the ones listed in this article), but graph doesn't return data for these attributes.

```<code>https://graph.microsoft.com/v1.0/users/<userId>?$select=id,alternativeSecurityId,alternativeSecurityIds,extension_<b2cExtensionAppId>_alternativeSecurityId,extension_<b2cExtensionAppId>_alternativeSecurityIds
</code>```

Thanks in advance!

答:
AlternativeSecurityId for a B2C user is found in the Identities collection via MS Graph API.

The AlternativeSecurityId claim used in the B2C policy maps to the Identities: issuerAssignedId value for the corresponding issuer.

Eg, for issuerAssignedId: 123 (id from google token) from issuer: google.com

  "identities": [
    {
      "signInType": "federated",
      "issuer": "google.com",
      "issuerAssignedId": "123"
    }
  ],
```

You can return the identities collection by calling the /users endpoint of MS Graph API. https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http

Body:
B2C uses an alternative security ID to uniquely identify users from social accounts.  We have a problem where a user enters credentials for a user, but somehow B2C authenticates the user as someone else.  I suspect the IDP is returning bad claims data or the alternative security IDs are the same.  How do I view the alternative security ID of a user in Active Directory?

I tried the following MS Graph query trying all the attributes I can think of (including the ones listed in this article), but graph doesn't return data for these attributes.

https://graph.microsoft.com/v1.0/users/<userId>?$select=id,alternativeSecurityId,alternativeSecurityIds,extension_<b2cExtensionAppId>_alternativeSecurityId,extension_<b2cExtensionAppId>_alternativeSecurityIds

Thanks in advance!

Body:
AlternativeSecurityId for a B2C user is found in the Identities collection via MS Graph API.

The AlternativeSecurityId claim used in the B2C policy maps to the Identities: issuerAssignedId value for the corresponding issuer.

Eg, for issuerAssignedId: 123 (id from google token) from issuer: google.com

  "identities": [
    {
      "signInType": "federated",
      "issuer": "google.com",
      "issuerAssignedId": "123"
    }
  ],

You can return the identities collection by calling the /users endpoint of MS Graph API. https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http


问:
Seam conditional render without parsing
I'm trying to make a conditional render in my Seam application (2.2.0), to display two different controls depending on a condition.

I'm using the s:fragment tag with the render attribute, but my problem is that I want whatever the control is displayed, to have the same id:

```<code><s:fragment render="${editable}">
  <rich:calendar id="entityDate"..../>
</s:fragment>
<s:fragment render="${!editable}">
  <h:outputText id="entityDate".../>
</s:fragment>
</code>```

My problem is that even when the render attribute set to false, the "not to be rendered" element is parsed, and I get an exception because of the duplicated id.

I also tried with the tag <ui:remove>, which effectively removes the element before the parsing phase, so I can have something like:

```<code><span id="myId"/>
<ui:remove>
  <span id="myId"/>
</ui:remove>
</code>```

Unfortunately the <ui:remove> tag doesn't allow conditional logic. Has anyone found a way to solve this?

答:
That's only possible when you use a view build time tag such as JSTL <c:if>.

```<code><c:if test="#{editable}">
    <rich:calendar id="entityDate" />
</c:if>
<c:if test="#{!editable}">
    <h:outputText id="entityDate" />
</c:if>
</code>```

(note that this is not going to work within an iterablte JSF component, such as <ui:repeat>, <h:dataTable> and so on)

After all, I strongly recommend to take benefit of the disabled attribute instead, if necessary with a good shot of CSS to hide the input field borders and so on. It'll minimize the JSF view boilerplate code.

```<code><rich:calendar id="entityDate" disabled="#{!editable}" />
</code>```

Disabled inputs are separately styleable by the CSS attribute selector element[attribute], e.g.

```<code>input[disabled] {
    border: 0;
}
</code>```

The above removes the border of input elements with the disabled attribute present so that it look like a normal output text.

Title: Seam conditional render without parsing

Body:
I'm trying to make a conditional render in my Seam application (2.2.0), to display two different controls depending on a condition.

I'm using the s:fragment tag with the render attribute, but my problem is that I want whatever the control is displayed, to have the same id:

<s:fragment render="${editable}">
  <rich:calendar id="entityDate"..../>
</s:fragment>
<s:fragment render="${!editable}">
  <h:outputText id="entityDate".../>
</s:fragment>

My problem is that even when the render attribute set to false, the "not to be rendered" element is parsed, and I get an exception because of the duplicated id.

I also tried with the tag <ui:remove>, which effectively removes the element before the parsing phase, so I can have something like:

<ui:remove>

</ui:remove>

Unfortunately the <ui:remove> tag doesn't allow conditional logic. Has anyone found a way to solve this?

Body:
That's only possible when you use a view build time tag such as JSTL <c:if>.

<c:if test="#{editable}">
    <rich:calendar id="entityDate" />
</c:if>
<c:if test="#{!editable}">
    <h:outputText id="entityDate" />
</c:if>

(note that this is not going to work within an iterablte JSF component, such as <ui:repeat>, <h:dataTable> and so on)

After all, I strongly recommend to take benefit of the disabled attribute instead, if necessary with a good shot of CSS to hide the input field borders and so on. It'll minimize the JSF view boilerplate code.

<rich:calendar id="entityDate" disabled="#{!editable}" />

Disabled inputs are separately styleable by the CSS attribute selector element[attribute], e.g.

input[disabled] {
    border: 0;
}

The above removes the border of input elements with the disabled attribute present so that it look like a normal output text.


问:
Using logical operators with expressions with multiple return values in lua
I'd like to do something like:

s,e = string.find(str, pattern1) or string.find(str, pattern2)
```

(because lua patterns don't have the equivalent of a regex |)

But this gives me nil for e even if one of the patterns matches.

How can I get both return values from the first function call to match?

答:
Lua lists are fragile, when used as an expression outside of very specific context (most importantly, if they're assigned to multiple names or as the last argument to a function), they devolve into their first value. To get the desired behaviour, you need to make sure to store all values. For example:</p>
```<code>local s1, e1 = string.find(str, pattern1)
if s1 then
    s, e = s1, e1
else
    s, e = string.find(str, pattern2)
end
</code>```

Body:
I'd like to do something like:

s,e = string.find(str, pattern1) or string.find(str, pattern2)

(because lua patterns don't have the equivalent of a regex |)

But this gives me nil for e even if one of the patterns matches.

How can I get both return values from the first function call to match?

Body:
Lua lists are fragile, when used as an expression outside of very specific context (most importantly, if they're assigned to multiple names or as the last argument to a function), they devolve into their first value. To get the desired behaviour, you need to make sure to store all values. For example:

local s1, e1 = string.find(str, pattern1)
if s1 then
    s, e = s1, e1
else
    s, e = string.find(str, pattern2)
end


问:
Insert into postgreSQL table from pandas with "on conflict" update
I have a pandas DataFrame that I need to store into the database. Here's my current line of code for inserting:

```<code>df.to_sql(table,con=engine,if_exists='append',index_label=index_col)
</code>```

This works fine if none of the rows in df exist in my table. If a row already exists, I get this error:

```<code>sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) duplicate key
value violates unique constraint "mypk"
DETAIL:  Key (id)=(42) already exists.
 [SQL: 'INSERT INTO mytable (id, owner,...) VALUES (%(id)s, %(owner)s,...']
 [parameters:...] (Background on this error at: http://sqlalche.me/e/gkpj)
</code>```

and nothing is inserted.

PostgreSQL has optional ON CONFLICT clause, which could be used to UPDATE the existing table rows. I read entire pandas.DataFrame.to_sql manual page and I couldn't find any way to use ON CONFLICT within DataFrame.to_sql() function.

I have considered spliting my DataFrame in two based on what's already in the db table. So now I have two DataFrames, insert_rows and update_rows, and I can safely execute

```<code>insert_rows.to_sql(table, con=engine, if_exists='append', index_label=index_col)
</code>```

But then, there seems to be no UPDATE equivalent to DataFrame.to_sql(). So how do I update the table using DataFrame update_rows?

答:
@ SaturnFromTitan, thanks for the reply to this old thread.  That worked like magic.   I would upvote, but I don't have the rep.

For those that are as new to all this as I am:
You can cut and paste SaturnFromTitan answer and call it with something like:

```<code>    df.to_sql('my_table_name',
              dbConnection,schema='my_schema',
              if_exists='append',
              index=False,
              method=postgres_upsert)
</code>```

And that's it.  The upsert works.

Body:
I have a pandas DataFrame that I need to store into the database. Here's my current line of code for inserting:

df.to_sql(table,con=engine,if_exists='append',index_label=index_col)

This works fine if none of the rows in df exist in my table. If a row already exists, I get this error:

sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) duplicate key
value violates unique constraint "mypk"
DETAIL:  Key (id)=(42) already exists.
 [SQL: 'INSERT INTO mytable (id, owner,...) VALUES (%(id)s, %(owner)s,...']
 [parameters:...] (Background on this error at: http://sqlalche.me/e/gkpj)

and nothing is inserted.

PostgreSQL has optional ON CONFLICT clause, which could be used to UPDATE the existing table rows. I read entire pandas.DataFrame.to_sql manual page and I couldn't find any way to use ON CONFLICT within DataFrame.to_sql() function.

I have considered spliting my DataFrame in two based on what's already in the db table. So now I have two DataFrames, insert_rows and update_rows, and I can safely execute

insert_rows.to_sql(table, con=engine, if_exists='append', index_label=index_col)

But then, there seems to be no UPDATE equivalent to DataFrame.to_sql(). So how do I update the table using DataFrame update_rows?

Body:
@ SaturnFromTitan, thanks for the reply to this old thread.  That worked like magic.   I would upvote, but I don't have the rep.

For those that are as new to all this as I am:
You can cut and paste SaturnFromTitan answer and call it with something like:

    df.to_sql('my_table_name',
              dbConnection,schema='my_schema',
              if_exists='append',
              index=False,
              method=postgres_upsert)

And that's it.  The upsert works.


问:
How do I run a JUnit test on an implemented class in Eclipse?
```<code>package evenodd;

public class HW3 { public static void main(String[] args) {
    MyInteger int1 = new MyInteger(5);
    MyInteger int2 = new MyInteger(38);
    MyInteger int3 = new MyInteger(10);
    MyInteger int4 = new MyInteger(5);

    System.out.printf("%d is even? %s%n", int1.getValue(), int1.isEven());
    System.out.printf("%d is even? %s%n", int2.getValue(), int2.isEven());
    System.out.printf("%d is even? %s%n", int3.getValue(), int3.isEven());

    System.out.printf("93 is odd? %s%n", MyInteger.isOdd(93));

    System.out.printf("%d equals %d? %s%n", int1.getValue(), int4.getValue(), int1.equals(int4));
    System.out.println("The value of int1 is equal to 5? " + int1.equals(5));
}
}

class MyInteger {
private int mValue;

public MyInteger(int value) {
    mValue = value;
}

public int getValue() {
    return mValue;
}

public boolean isEven() {
    return (mValue % 2) == 0;
}

public boolean isOdd() {
    return (mValue % 2) == 1;
}

public static boolean isEven(int myInt) {
    return (myInt % 2) == 0;
}

public static boolean isOdd(int myInt) {
    return (myInt % 2) == 1;
}

public static boolean isEven(MyInteger myInt) {
    return myInt.isEven();
}

public static boolean isOdd(MyInteger myInt) {
    return myInt.isOdd();
}

public boolean equals(int testInt) {
    if (testInt == mValue)
        return true;
    return false;
}

public boolean equals(MyInteger myInt) {
    if (myInt.mValue == this.mValue)
        return true;
    return false;
}
}
</code>```

I am trying to test the MyInteger class with JUnit in Eclipse but it keeps saying, "Class under test does not exist in current project." Does anyone know how to fix this? Also, I created a second source file in the java project with a package of the same name (evenodd) to put the JUnit test into because that's what this tutorial I was following said to do.

答:
If you need to perform a unit test on the MyInteger class,
you can simply add a Test Case to your project and create your @Tests:

```<code>import static org.junit.Assert.*;
import org.junit.Test;

public class MyIntegerTest {
    @Test
    public void testIsOdd() {
        MyInteger integer = new MyInteger(11);
        assertTrue(integer.isOdd());
    }
}
</code>```

Execution of IntegerTest

Body:
package evenodd;

public class HW3 { public static void main(String[] args) {
    MyInteger int1 = new MyInteger(5);
    MyInteger int2 = new MyInteger(38);
    MyInteger int3 = new MyInteger(10);
    MyInteger int4 = new MyInteger(5);

    System.out.printf("%d is even? %s%n", int1.getValue(), int1.isEven());
    System.out.printf("%d is even? %s%n", int2.getValue(), int2.isEven());
    System.out.printf("%d is even? %s%n", int3.getValue(), int3.isEven());

    System.out.printf("93 is odd? %s%n", MyInteger.isOdd(93));

    System.out.printf("%d equals %d? %s%n", int1.getValue(), int4.getValue(), int1.equals(int4));
    System.out.println("The value of int1 is equal to 5? " + int1.equals(5));
}
}

class MyInteger {
private int mValue;

public MyInteger(int value) {
    mValue = value;
}

public int getValue() {
    return mValue;
}

public boolean isEven() {
    return (mValue % 2) == 0;
}

public boolean isOdd() {
    return (mValue % 2) == 1;
}

public static boolean isEven(int myInt) {
    return (myInt % 2) == 0;
}

public static boolean isOdd(int myInt) {
    return (myInt % 2) == 1;
}

public static boolean isEven(MyInteger myInt) {
    return myInt.isEven();
}

public static boolean isOdd(MyInteger myInt) {
    return myInt.isOdd();
}

public boolean equals(int testInt) {
    if (testInt == mValue)
        return true;
    return false;
}

public boolean equals(MyInteger myInt) {
    if (myInt.mValue == this.mValue)
        return true;
    return false;
}
}

I am trying to test the MyInteger class with JUnit in Eclipse but it keeps saying, "Class under test does not exist in current project." Does anyone know how to fix this? Also, I created a second source file in the java project with a package of the same name (evenodd) to put the JUnit test into because that's what this tutorial I was following said to do.

Body:
If you need to perform a unit test on the MyInteger class,
you can simply add a Test Case to your project and create your @Tests:

import static org.junit.Assert.*;
import org.junit.Test;

public class MyIntegerTest {
    @Test
    public void testIsOdd() {
        MyInteger integer = new MyInteger(11);
        assertTrue(integer.isOdd());
    }
}

Execution of IntegerTest


问:
using same variable that is created in function into another function
I want to use 'number' variable that was created out of the function and use it in  couple functions and also give it an initial value 0, but it gives "local variable 'number' referenced before assignment" error at the last line of code.How could I fix it?Thanks in advance.</p>
```<code>lst_img=[img0,img1,img2,img3,img4]
number=0

def go_forward():

    global number
    number+=1
    shwimage.grid_forget()
    global shwimage1
    shwimage1=Label(image=lst_img[number])
    shwimage1.grid(row=0,column=0,columnspan=3)

def go_back():

   if number==0:
      shwimage.grid_forget()
   shwimage1.grid_forget()
   shwimage2=Label(image=lst_img[number-1])
   shwimage2.grid(row=0,column=0,columnspan=3)
   number-=1  # local variable 'number' referenced before assignment
</code>```

答:
I believe in go_back() function also, you are trying to reference the global variable number But it is not instructed to the function to use global number variable.</p>
```<code>def go_back():
   global number #This line needs to be addded
   if number==0:
      shwimage.grid_forget()
   shwimage1.grid_forget()
   shwimage2=Label(image=lst_img[number-1])
   shwimage2.grid(row=0,column=0,columnspan=3)
   number-=1
</code>```

Body:
I want to use 'number' variable that was created out of the function and use it in  couple functions and also give it an initial value 0, but it gives "local variable 'number' referenced before assignment" error at the last line of code.How could I fix it?Thanks in advance.

lst_img=[img0,img1,img2,img3,img4]
number=0

def go_forward():

    global number
    number+=1
    shwimage.grid_forget()
    global shwimage1
    shwimage1=Label(image=lst_img[number])
    shwimage1.grid(row=0,column=0,columnspan=3)

def go_back():

   if number==0:
      shwimage.grid_forget()
   shwimage1.grid_forget()
   shwimage2=Label(image=lst_img[number-1])
   shwimage2.grid(row=0,column=0,columnspan=3)
   number-=1  # local variable 'number' referenced before assignment

Body:
I believe in go_back() function also, you are trying to reference the global variable number But it is not instructed to the function to use global number variable.

def go_back():
   global number #This line needs to be addded
   if number==0:
      shwimage.grid_forget()
   shwimage1.grid_forget()
   shwimage2=Label(image=lst_img[number-1])
   shwimage2.grid(row=0,column=0,columnspan=3)
   number-=1


问:
Shannon-Fano Encoding with Images
I have been assigned to encode and decode images using the Shannon-Fano technique. I'll be writing in Matlab.

I am able to access the data array of the image in Matlab, so I can see the value of each pixel. I understand the basics of using the Shannon-Fano technique for text, but not images.

Would I need to loop through each pixel and count the number of occurrences for each pixel value?

Thanks for pointing me in the right direction.

答:
Imagine that this picture is actually a text and every pixel is a letter. If you have 8-bit picture, then you might have 256 different letters. How would you encode a text with 256 different letters? Yes, exactly the same way you encode text with 26 different letters, or 5 different letters, for that matter.

What you want to do in each case, is to make a histogram, sort it, based on frequency of each value, and then encode the image/text. So yes, you have to count each pixel value. Good luck!

Title: Shannon-Fano Encoding with Images


问:
Will 'Sleeping' apps receive push notifications from FCM?
I've been reading about non-standard app killing on https://dontkillmyapp.com/. In particular, I'm worried about how manufacturers are implementing mechanisms under the name of 'battery optimisations' which cripple the local notification API, by cancelling all alarms scheduled by an app after some time of inactivity: AlarmManager not working in several devices

Since there is no fix we as developers can implement to make local notifications work reliably, I'm wondering if I can just switch to push notifications. But I'm also not sure whether I can rely on push notifications, as there seems to be conflicting information:

Signal seem to say that their push notifications may be unreliable when battery optimisations are at work, though it's not clear whether this only applies to their custom web-socket push notification system, which it apparently uses when FCM isn't available: https://support.signal.org/hc/en-us/articles/360007318711-Troubleshooting-Notifications#android_notifications_troubleshooting_phone

It seems that push notifications which are sent via Firebase Cloud Messaging (FCM) will actually be received by the Google Play Services, so is it possible they may be received even if your app has been 'battery optimised'?

Can anyone shed some light on this? Can push notifications via FCM be more reliable than local notifications, when working around non-standard app killing?

答:
Apparently using FCM is no guarantee that notifications will be received - they may still fail to show due to non-standard battery optimisations.

This is documented by the following article:

https://hackernoon.com/notifications-in-android-are-horribly-broken-b8dbec63f48a

Which states that:

Google GCM said that the notification was sent but there was no trace of the notification in the app’s logs, it was as if the OS was swallowing notifications

After disabling battery optimisations, the notifications apparently worked again. Their workaround to this issue was:

GCM delivery receipts essentially tell you whether the device received the push notification or not. We coupled this with duplicate notification delivery receipts from inside of the app. So any device where we got ack’s from GCM but not from the device, was potentially missing pushes. Once the devices were identified, we started sending them bot messages on how to add flock in their device’s auto-start list.


问:
Can't SSH into AWS EC2 instance
I can't SSH into my EC2 instances - I am getting a timeout error. I checked the security groups to ensure that SSH traffic is working. I checked the routing tables and ensured that they are connected to an internet gateway. I was able to SSH into the instances just an hour ago but no longer. I am connecting via Putty. I had the same timeout issue connecting before using ec2-user@domain which I solved by simply entering the ip address into the hostname field in Putty. At that point I was able to connect without a problem. I then created another EC2 instance and now I cannot connect to either instance. I have the .ppk file being correctly referenced in my Putty config. I tried connecting with a mac and copying the .pem file there. Is there anything else I can check? Also, why could I not type ec2-user@domain into the connection field in putty like the directions indicate. Is there something wrong with my AWS environment?</p>

答:
Spencer's answer solved it for me.
It seems like that is the case, one small correction though: you need to edit the Outbound Rule on the Network ACL.

What I did from scratch:

Create VPC

Create a subnet in that VPC

Launch an EC2 instance

Follow: this link, add everything that they specify

Change the Network ACL outbound rule to contain the port range specified by Spencer: 1024-65535

Done, you can connect now

Note, that you won't be able to ping the instance if ICMP traffic is not allowed.

Title: Can't SSH into AWS EC2 instance


问:
How to get FormControlName of the field which value changed in Angular reactive forms
I have a reactive form with over 10 form controls and using subscription on valueChanges observable to detect changes. It works perfectly but output is always the entire form value object(meaning all the form controls and their values). Is there a way to simply get the form control name of the field that changed?</p>

```<code>this.form = this.fb.group({
    field1: ['', Validators.required],
    field2: ['', Validators.required],
    field3: ['', Validators.required],
    field4: ['', Validators.required],
    field5: ['', Validators.required],
    field6: ['', Validators.required],
    field7: ['', Validators.required],
    field8: ['', Validators.required],
    field9: ['', Validators.required],
    field10: ['', Validators.required],
    field11: ['', Validators.required],
    field12: ['', Validators.required],
    field13: [{ value: '', disabled: true }, Validators.required]
});

this.form.valueChanges.subscribe(
    result => this.calculateParams(result)
);

calculateParams(result) {
    console.log(result); // giving the entire form.value object
}
</code>```

答:
The method from @alex-walker (https://stackoverflow.com/a/64830665/134120) seems to be the best, but it only works well on flat forms, with simple key-value pairs. If you have nested forms, with FormArrays of FormGroups, the key property in that method will only return the top-level key of the form, which is not very useful if you want e.g. to indicate to the user the particular input field that triggered the event.

So I combined this method with a deep object diff method described here: https://stackoverflow.com/a/50278133/134120

To get something like this:

```<code>this.form.valueChanges
    .pipe(
        startWith(this.form.value),
        pairwise(),
        map(([oldValues, newValues]) => {
            return bdiff(oldValues, newValues);
        })
    )
    .subscribe(keys => {
        console.log(keys);
    });

bdiff(a: Record<string, any>, b: Record<string, any>): string[] {
    return _reduce(
        a,
        (res, val, key) =>
            res.concat(
                (_isPlainObject(val) || Array.isArray(val)) && b
                    ? this.bdiff(val, b[key]).map(x => key + (key.trim ? '' : ']') + (x.search(/^\d/) ? '.' : '[') + x)
                    : !b || val !== b[key]
                    ? [key + (key.trim ? '' : ']')]
                    : []
            ),
        []
    );
}

</code>```

Which will return an array of nested keys such as keys = ['fieldgroup2.fieldArray[3].myNestedField'] which you should easily access and set as invalid with form.get(keys[0]).valid.

Body:
I have a reactive form with over 10 form controls and using subscription on valueChanges observable to detect changes. It works perfectly but output is always the entire form value object(meaning all the form controls and their values). Is there a way to simply get the form control name of the field that changed?

this.form = this.fb.group({
    field1: ['', Validators.required],
    field2: ['', Validators.required],
    field3: ['', Validators.required],
    field4: ['', Validators.required],
    field5: ['', Validators.required],
    field6: ['', Validators.required],
    field7: ['', Validators.required],
    field8: ['', Validators.required],
    field9: ['', Validators.required],
    field10: ['', Validators.required],
    field11: ['', Validators.required],
    field12: ['', Validators.required],
    field13: [{ value: '', disabled: true }, Validators.required]
});

this.form.valueChanges.subscribe(
    result => this.calculateParams(result)
);

calculateParams(result) {
    console.log(result); // giving the entire form.value object
}

Body:
The method from @alex-walker (https://stackoverflow.com/a/64830665/134120) seems to be the best, but it only works well on flat forms, with simple key-value pairs. If you have nested forms, with FormArrays of FormGroups, the key property in that method will only return the top-level key of the form, which is not very useful if you want e.g. to indicate to the user the particular input field that triggered the event.

So I combined this method with a deep object diff method described here: https://stackoverflow.com/a/50278133/134120

To get something like this:

this.form.valueChanges
    .pipe(
        startWith(this.form.value),
        pairwise(),
        map(([oldValues, newValues]) => {
            return bdiff(oldValues, newValues);
        })
    )
    .subscribe(keys => {
        console.log(keys);
    });

bdiff(a: Record<string, any>, b: Record<string, any>): string[] {
    return _reduce(
        a,
        (res, val, key) =>
            res.concat(
                (_isPlainObject(val) || Array.isArray(val)) && b
                    ? this.bdiff(val, b[key]).map(x => key + (key.trim ? '' : ']') + (x.search(/^\d/) ? '.' : '[') + x)
                    : !b || val !== b[key]
                    ? [key + (key.trim ? '' : ']')]
                    : []
            ),
        []
    );
}

Which will return an array of nested keys such as keys = ['fieldgroup2.fieldArray[3].myNestedField'] which you should easily access and set as invalid with form.get(keys[0]).valid.


问:
Determine if a commit is a merge commit through Github API
Is it possible through the Github API to tell if a commit is a merge commit? And which branch it was merged from?

I am trying to look at all the files changed when comparing two commits on a branch, but I want to ignore any changes done by merge commits from the branch that it's branched from. Any branches that have branched off the branch will not have their merge commits ignored.

答:
```<code>curl \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/octocat/hello-world/commits
</code>```

You can use this API to fetch all the commits. After fetching all the commits the response would look like this as per GitHub's API documentation.

```<code>[

{
    "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==",
    "html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments",
    "commit": {
      "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
      "author": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "committer": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "message": "Fix all the bugs",
      "tree": {
        "url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      },
      "comment_count": 0,
      "verification": {
        "verified": false,
        "reason": "unsigned",
        "signature": null,
        "payload": null
      }
    },
    "author": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "committer": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "parents": [
      {
        "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      }
    ]
  }
]
</code>```

In the above payload, for each item in the array, if you have multiple lines in the "parents" key, then it means it is a merge commit. The above payload example has only one line in the "parents" array, so it is not a merge commit.

To find out which branch it was merged from, I believe there is currently no solution using the Github API.

Body:
curl \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/octocat/hello-world/commits

You can use this API to fetch all the commits. After fetching all the commits the response would look like this as per GitHub's API documentation.

[

{
    "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "node_id": "MDY6Q29tbWl0NmRjYjA5YjViNTc4NzVmMzM0ZjYxYWViZWQ2OTVlMmU0MTkzZGI1ZQ==",
    "html_url": "https://github.com/octocat/Hello-World/commit/6dcb09b5b57875f334f61aebed695e2e4193db5e",
    "comments_url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/comments",
    "commit": {
      "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
      "author": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "committer": {
        "name": "Monalisa Octocat",
        "email": "support@github.com",
        "date": "2011-04-14T16:00:49Z"
      },
      "message": "Fix all the bugs",
      "tree": {
        "url": "https://api.github.com/repos/octocat/Hello-World/tree/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      },
      "comment_count": 0,
      "verification": {
        "verified": false,
        "reason": "unsigned",
        "signature": null,
        "payload": null
      }
    },
    "author": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "committer": {
      "login": "octocat",
      "id": 1,
      "node_id": "MDQ6VXNlcjE=",
      "avatar_url": "https://github.com/images/error/octocat_happy.gif",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "site_admin": false
    },
    "parents": [
      {
        "url": "https://api.github.com/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e",
        "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e"
      }
    ]
  }
]

In the above payload, for each item in the array, if you have multiple lines in the "parents" key, then it means it is a merge commit. The above payload example has only one line in the "parents" array, so it is not a merge commit.

To find out which branch it was merged from, I believe there is currently no solution using the Github API.


问:
Android: How to Add Static row in list view
Android: How to Add Static row in list view
I have a requirement where i need to add the Static row as first row in list view

Thanks in advance for help..

答:
You can treat the the ListView layout just like any other layout and add everything you need to the layout design.

for example:

```<code><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView android:text="TextView" android:id="@+id/textView1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="0.91" android:textAppearance="?android:attr/textAppearanceLarge"></TextView>

    <ListView
        android:id="@id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="false" android:layout_weight="0.91"/>

</LinearLayout>
</code>```

Body:
You can treat the the ListView layout just like any other layout and add everything you need to the layout design.

for example:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView android:text="TextView" android:id="@+id/textView1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="0.91" android:textAppearance="?android:attr/textAppearanceLarge"></TextView>

    <ListView
        android:id="@id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="false" android:layout_weight="0.91"/>

</LinearLayout>


问:
How to add commit hash into reactjs vite.config.js
I want to add commit hash into my react app. Normally, I added it with webpack but this project they are using vite.config.js. May I know how to inject commit hash into vite and how can I use it in react component.

Thanks.

const commitHash = require('child_process').execSync('git rev-parse --short HEAD').toString();

答:
@Reiner, it is working for me. Here is tag I use in my react app.</p>
```<code><p className="text-center text-gray-500 text-xs">
    Version - {__COMMIT_HASH__}
</p>
</code>```

Body:
@Reiner, it is working for me. Here is tag I use in my react app.

<p className="text-center text-gray-500 text-xs">
    Version - {__COMMIT_HASH__}
</p>


问:
Firebase functions.config() not working even with .runtimeconfig.json in the correct location
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1"

I've been using firebase for almost a year now and all of a sudden my functions.config() is returning an empty object.

This is the error that I receive It looks like you're trying to access functions.config().myservice but there is no value there. Note that I have triple checked that there is no misspelling issue.

I know my .runtimeconfig.json is in the correct location (/functions/.runtimeconfig.json) with the existing object inside of it but it still isn't being called properly.

I've also ran npm run build to make sure it wasn't a TS not being compiled issue but apparently that's not the case.

One other thing I have done is created another functions directory on a different project, one using TS (it wouldn't function properly) and one with normal JavaScript and the latter was the only one that would run.

答: I have the same issue, but only after upgrading to firebase-tools@10.2.0. Downgrading to firebase-tools@10.1.5 is a workaround for me. From v10.2.0 and going forward, they are recommending using environment variables in the dotenv format instead of using functions.config().</p>


问:
remove header from a CSV in Google Cloud Funciton
I am Creating a CSV File from a Google Cloud Big Query Table.
Since I am converting the entire table into a CSV, by default the table header name is Included in the CSV file.

This is the Code I am using for creating the CSV file

```<code>  // Export data from the table into a Google Cloud Storage file
  const [job] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .extract(storage.bucket(bucketName).file(filename), options);

  console.log(`Job ${job.id} created.`);
</code>```

I have tried the following code to use to remove the header, did it doesn't work

```<code>const parser = csv({ headers : true });
</code>```

Any Idea how I can remove the header from the CSV??

答:
There is a printHeader option in the API definition. In the NodeJS client library, you can find the definition in the IJobConfigurationExtract

So, use printHeader:false in the options object

Body:
I am Creating a CSV File from a Google Cloud Big Query Table.
Since I am converting the entire table into a CSV, by default the table header name is Included in the CSV file.

This is the Code I am using for creating the CSV file

  // Export data from the table into a Google Cloud Storage file
  const [job] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .extract(storage.bucket(bucketName).file(filename), options);

  console.log(`Job ${job.id} created.`);

I have tried the following code to use to remove the header, did it doesn't work

const parser = csv({ headers : true });

Any Idea how I can remove the header from the CSV??


问:
Blazor: There is no boxing conversion or type parameter conversion from 'T' to 'System.IComparable<T>
Blazor doesn't seem to grasp my generic type constraints when using @typeparam.
The following setup gives a compilation error:

error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'MyObject<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IComparable<T>'.

MyObject.cs

```<code>public class MyObject<T>
    where T : IComparable<T>
{
    public MyObject(T value)
    {
        Value = value;
    }

    public T Value { get; }
}
</code>```

MyComponent.razor

```<code>@typeparam T where T : IComparable<T>
<div>
    @MyObject.Value
</div>

@code {
    [Parameter]
    public MyObject<T> MyObject { get; set; }
}
</code>```

MainComponent.razor

```<code><MyComponent MyObject="@value" />

@code {
    private MyObject<decimal> value = new MyObject(21M);
}
</code>```

I know I can add the type parameter explicitly, by doing this:

```<code><MyComponent T="decimal" MyObject="@value" />
</code>```

But in the codebase I'm about to write that will get very very cumbersome. It feels like blazor is supposed to be able to implicitly determine the type parameter used in the above example.

Is there a way to make this implicit type determination possible?

I'm using net6.0

答:
If MyObject<decimal> value was a parameter in the constructor for MyComponent then it would make sense that T could be implicitly determined. But Blazor needs to construct a new MyComponent long before any parameters in the type are actually set. So Blazor would have to know that you set all the parameters necessary for determining all type parameters, which it apparently doesn't do.

And you can see this by putting a breakpoint in the OnInitialized function of your component and seeing that value will not yet have any value.

You can see the lifecycle of the component here.

Plain C# example:

```<code>MyComponent c = new MyComponent<decimal>();  // <--- How must Blazor know this is a decimal here?
c.value = new MyObject(21M);
</code>```

Body:
Blazor doesn't seem to grasp my generic type constraints when using @typeparam.
The following setup gives a compilation error:

error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'MyObject<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IComparable<T>'.

MyObject.cs

public class MyObject<T>
    where T : IComparable<T>
{
    public MyObject(T value)
    {
        Value = value;
    }

    public T Value { get; }
}

MyComponent.razor

@typeparam T where T : IComparable<T>

    @MyObject.Value

@code {
    [Parameter]
    public MyObject<T> MyObject { get; set; }
}

MainComponent.razor

<MyComponent MyObject="@value" />

@code {
    private MyObject<decimal> value = new MyObject(21M);
}

I know I can add the type parameter explicitly, by doing this:

<MyComponent T="decimal" MyObject="@value" />

But in the codebase I'm about to write that will get very very cumbersome. It feels like blazor is supposed to be able to implicitly determine the type parameter used in the above example.

Is there a way to make this implicit type determination possible?

I'm using net6.0

Body:
If MyObject<decimal> value was a parameter in the constructor for MyComponent then it would make sense that T could be implicitly determined. But Blazor needs to construct a new MyComponent long before any parameters in the type are actually set. So Blazor would have to know that you set all the parameters necessary for determining all type parameters, which it apparently doesn't do.

And you can see this by putting a breakpoint in the OnInitialized function of your component and seeing that value will not yet have any value.

You can see the lifecycle of the component here.

Plain C# example:

MyComponent c = new MyComponent<decimal>();  // <--- How must Blazor know this is a decimal here?
c.value = new MyObject(21M);


问:
java compiler's target version "jsr14" with JDK7/8
Can anybody tell me the jsr14 target option of javac will be still available with JDK7/8?

Say,

```<code>$ javac -source 1.5 -target jsr14 Hello.java
</code>```

答:
We are heavily using -jsr14 in OSGi because it allows us to use generics in our API but still deploy on 1.4 environments, which are still popular in embedded. Unfortunately, they made JDK 7 not backward compatible with Java 6 and 5. Javac 1.7 ignores the generic information that is actually present in the JAR files. There is fortunately no problem at run-time as this info is ignored anyway. And it is not as if this was some undocumented feature ...

Unfortunately, people at the front often have very little regard for the people that cannot just update to the latest and the greatest. Guess Oracle really does not care about the embedded markets anymore.

We will likely now have to ship two JARs, one for the embedded and one for JDK 7. Sucks.

This is the bug report we filed: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7078419

Body:
Can anybody tell me the jsr14 target option of javac will be still available with JDK7/8?

Say,

$ javac -source 1.5 -target jsr14 Hello.java


问:
Dynamically name x-node of networkD3 sankey
I am trying to have produce a shiny application in which a Sankey plot, produced using NetworkD3, dynamically produces x-node labels. I think this requires passing a reactive element to onRender, but I am not sure how to do this.

I see an answer here: How to add columnn titles in a Sankey chart networkD3, but this solves the dynamic naming by calling .text("Step " + (i + 1)); in the onRender function. My labels are not so generic that I can just iterate and paste (the example below uses simplified names).

Here is an example:

```<code>library('shiny')
library('tidyverse')
library('networkD3')
library(shinyWidgets)
library(htmlwidgets)

#Create the data
df <- data.frame('A' = c('a', 'b', 'b', 'c', 'a'),
                 'B' = c('1', '1', '1', '2', '3'),
                 'C' = c('red', 'blue', 'blue', 'green', 'green'))

#Create the UI
ui <- fluidPage(
  #Sidebar to select x-nodes
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = 'var_select',
                  label = 'Variables',
                  choices = colnames(df),
                  selected = colnames(df),
                  multiple = TRUE,
                  pickerOptions(actionsBox = TRUE))
    ),
   #Mainpanel to show sankey plot
    mainPanel(
     sankeyNetworkOutput('plot',
                         height = '800px')
   )
  )
)

#Create the server
server <- function(input, session, output) {
  #create a reactive function that outputs the selected variables
  df_sankey <- reactive({
    df %>%
      select(input$var_select)
  })

  #Prepare for plotting in NetworkD3
  links1 <- reactive({
    df_sankey() %>%
      mutate(row = row_number()) %>%  # add a row id
      pivot_longer(-row, names_to = "col", values_to = "source") %>%  # gather all columns
      mutate(col = match(col, names(df_sankey()))) %>%  # convert col names to col ids
      mutate(source = paste0(source, '_', col)) %>%  # add col id to node names
      group_by(row) %>%
      mutate(target = lead(source, order_by = col)) %>%  # get target from following node in row
      ungroup() %>%
      filter(!is.na(target)) %>%  # remove links from last column in original data
      group_by(source, target) %>%
      summarise(value = n(), .groups = "drop")  # aggregate and count similar links
  })

  #Now create the nodes
  nodes <- reactive({
    data.frame(id = unique(c(links1()$source, links1()$target)),
               stringsAsFactors = F) %>%
      mutate(name = sub('_[0-9]*$', '', id))
  })

  #Mutate a soutrce id variable - have to create this as links2 to prevent endless recursion
  links2 <- reactive({
    mutate(links1(), source_id = match(links1()$source, nodes()$id) - 1)
  })

  #Do the same for target id
  links <- reactive({
    mutate(links2(), target_id = match(links2()$target, nodes()$id) - 1) %>%
      data.frame()
  })

  #Build the sankey plot
  plot1 <- reactive({
    sankeyNetwork(Links = links(), Nodes = nodes(),
                  Source = 'source_id', Target = 'target_id', Value = 'value', NodeID = 'name',
                  fontSize = 14)
  })

  #Here is the problematic code
  #under code starting var labels - i need that to be produced by a reactive element: colnames(df_sankey())
  #Without this it just take the number of var labels as there are selected variables
  output$plot <- renderSankeyNetwork({
    onRender(plot1(), '
      function(el) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = ["A", "B", "C"];
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }
    ')
  })

}

#call the application
shinyApp(ui, server)
</code>```

I call out the problem in the comments above the onRender function. Effectively I need var labels to take a reactive function generated by something like: colnames(df_sankey()). If i put that code in for var labels (which i appreciate is a wild guess), it just fails. Without the reactive function the code just loops through the var labels according to the number of variables selected. You can see the problem if you select var A and C - C gets labelled B. I also tried (another guess):

```<code>  output$plot <- renderSankeyNetwork({
    onRender(plot1(), '
      function(el, node_labels) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = [node_labels];
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }
    ', node_labels = colnames(df_sankey()))
</code>```

But that also fails. I can't seem to find an explanation for how to pass reactive functions to onRender.

How can I pass a reactive function to the onRender function so that i can dynamically name my x-nodes?

答:
Full working code for the above example posted below:</p>
```<code>library('shiny')
library('tidyverse')
library('networkD3')
library('shinyWidgets')
library('htmlwidgets')

#Create the data
df <- data.frame('A' = c('a', 'b', 'b', 'c', 'a'),
                 'B' = c('1', '1', '1', '2', '3'),
                 'C' = c('red', 'blue', 'blue', 'green', 'green'))

#Create the UI
ui <- fluidPage(
  #Sidebar to select x-nodes
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = 'var_select',
                  label = 'Variables',
                  choices = colnames(df),
                  selected = colnames(df),
                  multiple = TRUE,
                  pickerOptions(actionsBox = TRUE))
    ),
   #Mainpanel to show sankey plot
    mainPanel(
     sankeyNetworkOutput('plot',
                         height = '800px')
   )
  )
)

#Create the server
server <- function(input, session, output) {
  #create a reactive function that outputs the selected variables
  df_sankey <- reactive({
    df %>%
      select(input$var_select)
  })
  #create a reactive function for the array that will populate the var labels
  col_lables_js_arrray_string <- reactive({
    paste0('["', paste(colnames(df_sankey()), collapse = '", "'), '"]')
  })

  #Prepare for plotting in NetworkD3
  links1 <- reactive({
    df_sankey() %>%
      mutate(row = row_number()) %>%  # add a row id
      pivot_longer(-row, names_to = "col", values_to = "source") %>%  # gather all columns
      mutate(col = match(col, names(df_sankey()))) %>%  # convert col names to col ids
      mutate(source = paste0(source, '_', col)) %>%  # add col id to node names
      group_by(row) %>%
      mutate(target = lead(source, order_by = col)) %>%  # get target from following node in row
      ungroup() %>%
      filter(!is.na(target)) %>%  # remove links from last column in original data
      group_by(source, target) %>%
      summarise(value = n(), .groups = "drop")  # aggregate and count similar links
  })

  #Now create the nodes
  nodes <- reactive({
    data.frame(id = unique(c(links1()$source, links1()$target)),
               stringsAsFactors = F) %>%
      mutate(name = sub('_[0-9]*$', '', id))
  })

  #Mutate a soutrce id variable - have to create this as links2 to prevent endless recursion
  links2 <- reactive({
    mutate(links1(), source_id = match(links1()$source, nodes()$id) - 1)
  })

  #Do the same for target id
  links <- reactive({
    mutate(links2(), target_id = match(links2()$target, nodes()$id) - 1) %>%
      data.frame()
  })

  #Build the sankey plot
  plot1 <- reactive({
    sankeyNetwork(Links = links(), Nodes = nodes(),
                  Source = 'source_id', Target = 'target_id', Value = 'value', NodeID = 'name',
                  fontSize = 14)
  })
  #paste the array for the var labels into the string that will run as valid js code
  render_js <- reactive({
    paste('function(el) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = ',col_lables_js_arrray_string(),';
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }')
  })

  #render the sankey network, by calling the reactive js code string
  output$plot <- renderSankeyNetwork({
    onRender(plot1(), jsCode = render_js())
  })

}

#call the application
shinyApp(ui, server)
</code>```

Body:
I am trying to have produce a shiny application in which a Sankey plot, produced using NetworkD3, dynamically produces x-node labels. I think this requires passing a reactive element to onRender, but I am not sure how to do this.

I see an answer here: How to add columnn titles in a Sankey chart networkD3, but this solves the dynamic naming by calling .text("Step " + (i + 1)); in the onRender function. My labels are not so generic that I can just iterate and paste (the example below uses simplified names).

Here is an example:

library('shiny')
library('tidyverse')
library('networkD3')
library(shinyWidgets)
library(htmlwidgets)

#Create the data
df <- data.frame('A' = c('a', 'b', 'b', 'c', 'a'),
                 'B' = c('1', '1', '1', '2', '3'),
                 'C' = c('red', 'blue', 'blue', 'green', 'green'))

#Create the UI
ui <- fluidPage(
  #Sidebar to select x-nodes
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = 'var_select',
                  label = 'Variables',
                  choices = colnames(df),
                  selected = colnames(df),
                  multiple = TRUE,
                  pickerOptions(actionsBox = TRUE))
    ),
   #Mainpanel to show sankey plot
    mainPanel(
     sankeyNetworkOutput('plot',
                         height = '800px')
   )
  )
)

#Create the server
server <- function(input, session, output) {
  #create a reactive function that outputs the selected variables
  df_sankey <- reactive({
    df %>%
      select(input$var_select)
  })

  #Prepare for plotting in NetworkD3
  links1 <- reactive({
    df_sankey() %>%
      mutate(row = row_number()) %>%  # add a row id
      pivot_longer(-row, names_to = "col", values_to = "source") %>%  # gather all columns
      mutate(col = match(col, names(df_sankey()))) %>%  # convert col names to col ids
      mutate(source = paste0(source, '_', col)) %>%  # add col id to node names
      group_by(row) %>%
      mutate(target = lead(source, order_by = col)) %>%  # get target from following node in row
      ungroup() %>%
      filter(!is.na(target)) %>%  # remove links from last column in original data
      group_by(source, target) %>%
      summarise(value = n(), .groups = "drop")  # aggregate and count similar links
  })

  #Now create the nodes
  nodes <- reactive({
    data.frame(id = unique(c(links1()$source, links1()$target)),
               stringsAsFactors = F) %>%
      mutate(name = sub('_[0-9]*$', '', id))
  })

  #Mutate a soutrce id variable - have to create this as links2 to prevent endless recursion
  links2 <- reactive({
    mutate(links1(), source_id = match(links1()$source, nodes()$id) - 1)
  })

  #Do the same for target id
  links <- reactive({
    mutate(links2(), target_id = match(links2()$target, nodes()$id) - 1) %>%
      data.frame()
  })

  #Build the sankey plot
  plot1 <- reactive({
    sankeyNetwork(Links = links(), Nodes = nodes(),
                  Source = 'source_id', Target = 'target_id', Value = 'value', NodeID = 'name',
                  fontSize = 14)
  })

  #Here is the problematic code
  #under code starting var labels - i need that to be produced by a reactive element: colnames(df_sankey())
  #Without this it just take the number of var labels as there are selected variables
  output$plot <- renderSankeyNetwork({
    onRender(plot1(), '
      function(el) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = ["A", "B", "C"];
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }
    ')
  })

}

#call the application
shinyApp(ui, server)

I call out the problem in the comments above the onRender function. Effectively I need var labels to take a reactive function generated by something like: colnames(df_sankey()). If i put that code in for var labels (which i appreciate is a wild guess), it just fails. Without the reactive function the code just loops through the var labels according to the number of variables selected. You can see the problem if you select var A and C - C gets labelled B. I also tried (another guess):

  output$plot <- renderSankeyNetwork({
    onRender(plot1(), '
      function(el, node_labels) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = [node_labels];
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }
    ', node_labels = colnames(df_sankey()))

But that also fails. I can't seem to find an explanation for how to pass reactive functions to onRender.

How can I pass a reactive function to the onRender function so that i can dynamically name my x-nodes?

Body:
Full working code for the above example posted below:

library('shiny')
library('tidyverse')
library('networkD3')
library('shinyWidgets')
library('htmlwidgets')

#Create the data
df <- data.frame('A' = c('a', 'b', 'b', 'c', 'a'),
                 'B' = c('1', '1', '1', '2', '3'),
                 'C' = c('red', 'blue', 'blue', 'green', 'green'))

#Create the UI
ui <- fluidPage(
  #Sidebar to select x-nodes
  sidebarLayout(
    sidebarPanel(
      pickerInput(inputId = 'var_select',
                  label = 'Variables',
                  choices = colnames(df),
                  selected = colnames(df),
                  multiple = TRUE,
                  pickerOptions(actionsBox = TRUE))
    ),
   #Mainpanel to show sankey plot
    mainPanel(
     sankeyNetworkOutput('plot',
                         height = '800px')
   )
  )
)

#Create the server
server <- function(input, session, output) {
  #create a reactive function that outputs the selected variables
  df_sankey <- reactive({
    df %>%
      select(input$var_select)
  })
  #create a reactive function for the array that will populate the var labels
  col_lables_js_arrray_string <- reactive({
    paste0('["', paste(colnames(df_sankey()), collapse = '", "'), '"]')
  })

  #Prepare for plotting in NetworkD3
  links1 <- reactive({
    df_sankey() %>%
      mutate(row = row_number()) %>%  # add a row id
      pivot_longer(-row, names_to = "col", values_to = "source") %>%  # gather all columns
      mutate(col = match(col, names(df_sankey()))) %>%  # convert col names to col ids
      mutate(source = paste0(source, '_', col)) %>%  # add col id to node names
      group_by(row) %>%
      mutate(target = lead(source, order_by = col)) %>%  # get target from following node in row
      ungroup() %>%
      filter(!is.na(target)) %>%  # remove links from last column in original data
      group_by(source, target) %>%
      summarise(value = n(), .groups = "drop")  # aggregate and count similar links
  })

  #Now create the nodes
  nodes <- reactive({
    data.frame(id = unique(c(links1()$source, links1()$target)),
               stringsAsFactors = F) %>%
      mutate(name = sub('_[0-9]*$', '', id))
  })

  #Mutate a soutrce id variable - have to create this as links2 to prevent endless recursion
  links2 <- reactive({
    mutate(links1(), source_id = match(links1()$source, nodes()$id) - 1)
  })

  #Do the same for target id
  links <- reactive({
    mutate(links2(), target_id = match(links2()$target, nodes()$id) - 1) %>%
      data.frame()
  })

  #Build the sankey plot
  plot1 <- reactive({
    sankeyNetwork(Links = links(), Nodes = nodes(),
                  Source = 'source_id', Target = 'target_id', Value = 'value', NodeID = 'name',
                  fontSize = 14)
  })
  #paste the array for the var labels into the string that will run as valid js code
  render_js <- reactive({
    paste('function(el) {
        var cols_x = this.sankey.nodes().map(d => d.x).filter((v, i, a) => a.indexOf(v) === i).sort(function(a, b){return a - b});
        var labels = ',col_lables_js_arrray_string(),';
        cols_x.forEach((d, i) => {
          d3.select(el).select("svg")
            .append("text")
            .attr("x", d)
            .attr("y", 12)
            .text(labels[i]);
        })
      }')
  })

  #render the sankey network, by calling the reactive js code string
  output$plot <- renderSankeyNetwork({
    onRender(plot1(), jsCode = render_js())
  })

}

#call the application
shinyApp(ui, server)