问:
purrr + dplyr NSE issues inside a user written function
After a lot of trial and error and consultation with previous answers such as How to detect if bare variable or string I think I have gotten most of what I need done myself.  But I'm eager to understand if I'm making some bad assumptions or approaching the problem foolishly before I carry my "solution" into production.

Consider the following data:

library(dplyr)
library(purrr)
library(tidyselect)

set.seed(1111)
dat1 <- data.frame(Region = rep(c("r1","r2"), each = 100),
                   State = rep(c("NY","MA","FL","GA"), each = 10),
                   Loc = rep(c("a","b","c","d","e","f","g","h"),each = 5),
                   ID = rep(c(1:10), each = 2),
                   var1 = rnorm(200),
                   var2 = rnorm(200),
                   var3 = rnorm(200),
                   var4 = rnorm(200),
                   var5 = rnorm(200))
```

<p>I want to write a function that does quite a few things but I'll start with a minimum reproducible example.  I want to get <code>tidied</code> <code>aov</code> results back either for a singular case <code>var1 ~ State</code> or for a pair of matched lists using <code>map2</code> with one list containing <em>"outcomes"</em> the other <em>"predictors"</em>.  They're never identical from use to use and the variables, unlike my example, rarely lend themselves to easy solutions like <code>starts_with</code>.</p>

<p>Two specific issues and a generic question.</p>

<p>Issue #1 - I've given up on allowing end users (including me) to pass in bare variable names always gets me in trouble later. In accordance with the reference above is something like my code the fastest most reliable way to catch them and tell the user? (I put a comment in the code to indicate where I'm talking about.</p>

<p>Issue #2 - Through basically trail and error I think I solved my other problem which is in generating some text for use later as a label.  I found lots of solutions when I'm not using the function with <code>map2</code> but only this one seems to work with map2.  It seems so convoluted I can't believe it's a good choice... (again comments in code to show where)</p>

<p>Generic question: I've added the recommended <code>tidyselect::all_of</code> because these might be ambiguous lists, why am I still having to guard against the <code>.x</code> and <code>.y</code> being seen as calls as opposed to just markers for iteration?</p>

<pre class="lang-r prettyprint-override"><code>MyFunction <- function(data,
                 groupvar,
                 var) {
  # Issue #1 is this best way to warn/stop user?
  lst <- as.list(match.call())

  if (is.symbol(lst$groupvar) || is.symbol(lst$var)) {
    stop("Please quote all variables")
  }

  # Issue #2 I want the group label but if I don't include
  # this if logic it errors with " Error: Can't convert a call to a string"
  # when I run it with purrr::map2
  if (!is.call(groupvar)) {
     grouplabel <- rlang::as_name(rlang::enquo(groupvar))
  }

  data <-
    dplyr::select(
      .data = data,
      var = {{ var }},
      groupvar = {{ groupvar }}
    )

  aov_object <- aov(var ~ groupvar, data = data)
  aov_results <- broom::tidy(aov_object) %>%
    mutate(term = if_else(term != "Residuals", grouplabel, term))
  return(aov_results)
}

# Expected output

MyFunction(data = dat1, groupvar = "State", var = "var1") # works
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = State, var = var1) # warns appropriately
#> Error in MyFunction(data = dat1, groupvar = State, var = var1): Please quote all variables

# Quick test of `map2`
grouping_vars <- names(dat1[,1:3])
names(grouping_vars) <- names(dat1[,1:3])

outcome_vars <- names(dat1[,5:7])
names(outcome_vars) <- names(dat1[,5:7])

names(outcome_vars) <- paste(outcome_vars, "~", grouping_vars)

# get multiple results this is where issue #2 comes in but this is what I want it to look like.

map2(.x = outcome_vars,
     .y = grouping_vars,
     .f = ~ MyFunction(dat = dat1,
                 var = tidyselect::all_of(.x),
                 groupvar = tidyselect::all_of(.y)))
#> $`var1 ~ Region`
#> # A tibble: 2 x 6
#>   term         df    sumsq meansq statistic p.value
#>   <chr>     <dbl>    <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Region        1   0.0512 0.0512    0.0427   0.836
#> 2 Residuals   198 237.     1.20     NA       NA
#>
#> $`var2 ~ State`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   5.05  1.68       2.07   0.106
#> 2 Residuals   196 159.    0.814     NA     NA
#>
#> $`var3 ~ Loc`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Loc           7   5.09  0.727     0.772   0.612
#> 2 Residuals   192 181.    0.943    NA      NA
</code>```

答:
It seems to me that since you are insistent on passing strings as variable names it would be simpler and more efficient to change the formula to match the variables using as.formula rather than changing the data. This also prevents you having to separately name the grouping variable inside the function.

The following function is shorter and about twice as fast in benchmarking as the original, but the behaviour remains unchanged:

```<code>MyFunctionNew <- function(data, groupvar, var)
{
  lst <- as.list(match.call())
  if (is.symbol(lst$groupvar) || is.symbol(lst$var))
    stop("Please quote all variables")

  broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
    mutate(term = if_else(term != "Residuals", groupvar, term))
}
</code>```

You can see that it still works inside map2:

```<code>map2(.x = outcome_vars,
     .y = grouping_vars,
     .f = ~ MyFunctionNew(dat = dat1,
                       var = tidyselect::all_of(.x),
                       groupvar = tidyselect::all_of(.y)))
#> $`var1 ~ Region`
#> # A tibble: 2 x 6
#>   term         df    sumsq meansq statistic p.value
#>   <chr>     <dbl>    <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Region        1   0.0512 0.0512    0.0427   0.836
#> 2 Residuals   198 237.     1.20     NA       NA
#>
#> $`var2 ~ State`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   5.05  1.68       2.07   0.106
#> 2 Residuals   196 159.    0.814     NA     NA
#>
#> $`var3 ~ Loc`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Loc           7   5.09  0.727     0.772   0.612
#> 2 Residuals   192 181.    0.943    NA      NA
</code>```

In terms of screening variables to ensure they are character strings, I don't think this is idiomatic R usage, and could cause some confusion to casual users of your function. In other words, it violates the principle of least astonishment.

For example, as a naive user, I would expect to be able to specify the grouping variable programatically like this:

```<code>MyVar <- "State"
MyFunction(data = dat1, groupvar = MyVar, var = "var1")
</code>```

However, I get an error telling me that all variables should be quoted.

This also means that your function won't work within base R loops and *apply functions:

```<code>lapply(c("State", "Region", "ID"), function(x) MyFunction(dat1, x, "var1"))
#> Error in MyFunction(dat1, x, "var1") : Please quote all variables
</code>```

I think this is far more confusing and limiting than just allowing an error to be thrown when an unquoted column name is used. Therefore, I think your production function should be something like:

```<code>MyFunction <- function(data, groupvar, var)
{
  broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
    mutate(term = if_else(term != "Residuals", groupvar, term))
}
</code>```

Which performs like this:

```<code>MyFunction(data = dat1, groupvar = "State", var = "var1")
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = MyVar, var = "var1")
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = State, var = var1)
#>  Error in paste(var, "~", groupvar) : object 'State' not found
</code>```

I think most R users would realise why they were getting this last error, since it is pretty clear. It is also an error that regular R users will have seen many times. If you have less faith in your users, perhaps you could try wrapping the function body in a tryCatch that converts a "symbol not found error" to a "please use quotes" error.

Ultimately, it may be best to write the function so that it takes naked symbols, but I get the impression you are keen to avoid that and so I won't labour the point here.

Body:
After a lot of trial and error and consultation with previous answers such as How to detect if bare variable or string I think I have gotten most of what I need done myself.  But I'm eager to understand if I'm making some bad assumptions or approaching the problem foolishly before I carry my "solution" into production.

Consider the following data:

library(dplyr)
library(purrr)
library(tidyselect)

set.seed(1111)
dat1 <- data.frame(Region = rep(c("r1","r2"), each = 100),
                   State = rep(c("NY","MA","FL","GA"), each = 10),
                   Loc = rep(c("a","b","c","d","e","f","g","h"),each = 5),
                   ID = rep(c(1:10), each = 2),
                   var1 = rnorm(200),
                   var2 = rnorm(200),
                   var3 = rnorm(200),
                   var4 = rnorm(200),
                   var5 = rnorm(200))

I want to write a function that does quite a few things but I'll start with a minimum reproducible example.  I want to get tidied aov results back either for a singular case var1 ~ State or for a pair of matched lists using map2 with one list containing "outcomes" the other "predictors".  They're never identical from use to use and the variables, unlike my example, rarely lend themselves to easy solutions like starts_with.

Two specific issues and a generic question.

Issue #1 - I've given up on allowing end users (including me) to pass in bare variable names always gets me in trouble later. In accordance with the reference above is something like my code the fastest most reliable way to catch them and tell the user? (I put a comment in the code to indicate where I'm talking about.

Issue #2 - Through basically trail and error I think I solved my other problem which is in generating some text for use later as a label.  I found lots of solutions when I'm not using the function with map2 but only this one seems to work with map2.  It seems so convoluted I can't believe it's a good choice... (again comments in code to show where)

Generic question: I've added the recommended tidyselect::all_of because these might be ambiguous lists, why am I still having to guard against the .x and .y being seen as calls as opposed to just markers for iteration?

MyFunction <- function(data,
                 groupvar,
                 var) {
  # Issue #1 is this best way to warn/stop user?
  lst <- as.list(match.call())

  if (is.symbol(lst$groupvar) || is.symbol(lst$var)) {
    stop("Please quote all variables")
  }

  # Issue #2 I want the group label but if I don't include
  # this if logic it errors with " Error: Can't convert a call to a string"
  # when I run it with purrr::map2
  if (!is.call(groupvar)) {
     grouplabel <- rlang::as_name(rlang::enquo(groupvar))
  }

  data <-
    dplyr::select(
      .data = data,
      var = {{ var }},
      groupvar = {{ groupvar }}
    )

  aov_object <- aov(var ~ groupvar, data = data)
  aov_results <- broom::tidy(aov_object) %>%
    mutate(term = if_else(term != "Residuals", grouplabel, term))
  return(aov_results)
}

# Expected output

MyFunction(data = dat1, groupvar = "State", var = "var1") # works
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = State, var = var1) # warns appropriately
#> Error in MyFunction(data = dat1, groupvar = State, var = var1): Please quote all variables

# Quick test of `map2`
grouping_vars <- names(dat1[,1:3])
names(grouping_vars) <- names(dat1[,1:3])

outcome_vars <- names(dat1[,5:7])
names(outcome_vars) <- names(dat1[,5:7])

names(outcome_vars) <- paste(outcome_vars, "~", grouping_vars)

# get multiple results this is where issue #2 comes in but this is what I want it to look like.

map2(.x = outcome_vars,
     .y = grouping_vars,
     .f = ~ MyFunction(dat = dat1,
                 var = tidyselect::all_of(.x),
                 groupvar = tidyselect::all_of(.y)))
#> $`var1 ~ Region`
#> # A tibble: 2 x 6
#>   term         df    sumsq meansq statistic p.value
#>   <chr>     <dbl>    <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Region        1   0.0512 0.0512    0.0427   0.836
#> 2 Residuals   198 237.     1.20     NA       NA
#>
#> $`var2 ~ State`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   5.05  1.68       2.07   0.106
#> 2 Residuals   196 159.    0.814     NA     NA
#>
#> $`var3 ~ Loc`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Loc           7   5.09  0.727     0.772   0.612
#> 2 Residuals   192 181.    0.943    NA      NA

Body:
It seems to me that since you are insistent on passing strings as variable names it would be simpler and more efficient to change the formula to match the variables using as.formula rather than changing the data. This also prevents you having to separately name the grouping variable inside the function.

The following function is shorter and about twice as fast in benchmarking as the original, but the behaviour remains unchanged:

MyFunctionNew <- function(data, groupvar, var)
{
  lst <- as.list(match.call())
  if (is.symbol(lst$groupvar) || is.symbol(lst$var))
    stop("Please quote all variables")

  broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
    mutate(term = if_else(term != "Residuals", groupvar, term))
}

You can see that it still works inside map2:

map2(.x = outcome_vars,
     .y = grouping_vars,
     .f = ~ MyFunctionNew(dat = dat1,
                       var = tidyselect::all_of(.x),
                       groupvar = tidyselect::all_of(.y)))
#> $`var1 ~ Region`
#> # A tibble: 2 x 6
#>   term         df    sumsq meansq statistic p.value
#>   <chr>     <dbl>    <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Region        1   0.0512 0.0512    0.0427   0.836
#> 2 Residuals   198 237.     1.20     NA       NA
#>
#> $`var2 ~ State`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   5.05  1.68       2.07   0.106
#> 2 Residuals   196 159.    0.814     NA     NA
#>
#> $`var3 ~ Loc`
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 Loc           7   5.09  0.727     0.772   0.612
#> 2 Residuals   192 181.    0.943    NA      NA

In terms of screening variables to ensure they are character strings, I don't think this is idiomatic R usage, and could cause some confusion to casual users of your function. In other words, it violates the principle of least astonishment.

For example, as a naive user, I would expect to be able to specify the grouping variable programatically like this:

MyVar <- "State"
MyFunction(data = dat1, groupvar = MyVar, var = "var1")

However, I get an error telling me that all variables should be quoted.

This also means that your function won't work within base R loops and *apply functions:

lapply(c("State", "Region", "ID"), function(x) MyFunction(dat1, x, "var1"))
#> Error in MyFunction(dat1, x, "var1") : Please quote all variables

I think this is far more confusing and limiting than just allowing an error to be thrown when an unquoted column name is used. Therefore, I think your production function should be something like:

MyFunction <- function(data, groupvar, var)
{
  broom::tidy(aov(as.formula(paste(var, "~", groupvar)), data = data)) %>%
    mutate(term = if_else(term != "Residuals", groupvar, term))
}

Which performs like this:

MyFunction(data = dat1, groupvar = "State", var = "var1")
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = MyVar, var = "var1")
#> # A tibble: 2 x 6
#>   term         df  sumsq meansq statistic p.value
#>   <chr>     <dbl>  <dbl>  <dbl>     <dbl>   <dbl>
#> 1 State         3   1.75  0.582     0.485   0.693
#> 2 Residuals   196 235.    1.20     NA      NA

MyFunction(data = dat1, groupvar = State, var = var1)
#>  Error in paste(var, "~", groupvar) : object 'State' not found

I think most R users would realise why they were getting this last error, since it is pretty clear. It is also an error that regular R users will have seen many times. If you have less faith in your users, perhaps you could try wrapping the function body in a tryCatch that converts a "symbol not found error" to a "please use quotes" error.

Ultimately, it may be best to write the function so that it takes naked symbols, but I get the impression you are keen to avoid that and so I won't labour the point here.


来源: stackexchange

问:
Change information on hover of Plotly point
I'm using Plotly in R to make a scatter plot but currently when I hover over the point in my shiny app, the values corresponding to the x,y values appear. ex (19, 27.73k). However, I would like to change it to display a column corresponding to that data as well. ex (USA, 19, 27.73k) Would this be possible? IDK if relevant but current marker code</p>

```<code>mode="markers",
               marker = list(
                 opacity = 0.5,
                 size = 5
               )) %>%
</code>```

答: What you're looking for is hovertemplate, possibly in tandem with text.  Without data it's hard to generate exactly what you need, but you should be able to figure it out at https://plotly.com/r/hover-text-and-formatting/

ContentLicense: CC BY-SA 4.0

Body:
I'm using Plotly in R to make a scatter plot but currently when I hover over the point in my shiny app, the values corresponding to the x,y values appear. ex (19, 27.73k). However, I would like to change it to display a column corresponding to that data as well. ex (USA, 19, 27.73k) Would this be possible? IDK if relevant but current marker code

mode="markers",
               marker = list(
                 opacity = 0.5,
                 size = 5
               )) %>%


问:
redirect output of gcloud command to a file in cloud build
I am using cloudbuild.yml file.

I am trying to grab the build output from inside the cloud build and push it to a file. This is how my step looks like:

```<code>- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
  args: ['gcloud', 'builds', 'log', '$BUILD_ID', '>buildlog.log']
  id: 'fetch-build-log'
</code>```

This throws me an error saying ERROR: (gcloud.builds.log) unrecognized arguments: >buildlog.log

If I execute that command in cloud shell, it works fine: gcloud builds log xxxxx-xxxx-xxxx-xxxx-xxxxxxx >guildlog.log

I am not sure why cloud build considers >buildlog.log an argument when it is to redirect the output to the file.

Am I missing something here or is there another way of doing it?

答:
In Cloud Build each builder has a default entrypoint, which typically correlates to that builder’s purpose.

In your example, you are using cloud-sdk default entrypoint and the positional args syntax, so each index should be a single argument.

That's why you receive the error: ERROR: (gcloud.builds.log) unrecognized arguments: >buildlog.log

I put together a working example changing the entrypoint to /bin/bash:

```<code>steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
  entrypoint: '/bin/bash'
  args: ['-c',
         'gcloud builds log $BUILD_ID > buildlog.log']
  id: 'fetch-build-log'
- name: 'alpine'
  id: 'OUTPUT_LOG'
  args: ['sh',
         '-c',
         'cat /workspace/buildlog.log']
</code>```

In that example I'm using the -c command, in case you want to understand why:

Quoting from man bash:

```<code>   -c string If the -c option is present,  then  commands  are  read  from
             string.   If  there  are arguments after the string, they are
             assigned to the positional parameters, starting with $0.
</code>```

Let me know if it works for you.

Body:
I am using cloudbuild.yml file.

I am trying to grab the build output from inside the cloud build and push it to a file. This is how my step looks like:

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
  args: ['gcloud', 'builds', 'log', '$BUILD_ID', '>buildlog.log']
  id: 'fetch-build-log'

This throws me an error saying ERROR: (gcloud.builds.log) unrecognized arguments: >buildlog.log

If I execute that command in cloud shell, it works fine: gcloud builds log xxxxx-xxxx-xxxx-xxxx-xxxxxxx >guildlog.log

I am not sure why cloud build considers >buildlog.log an argument when it is to redirect the output to the file.

Am I missing something here or is there another way of doing it?

Body:
In Cloud Build each builder has a default entrypoint, which typically correlates to that builder’s purpose.

In your example, you are using cloud-sdk default entrypoint and the positional args syntax, so each index should be a single argument.

That's why you receive the error: ERROR: (gcloud.builds.log) unrecognized arguments: >buildlog.log

I put together a working example changing the entrypoint to /bin/bash:

steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
  entrypoint: '/bin/bash'
  args: ['-c',
         'gcloud builds log $BUILD_ID > buildlog.log']
  id: 'fetch-build-log'
- name: 'alpine'
  id: 'OUTPUT_LOG'
  args: ['sh',
         '-c',
         'cat /workspace/buildlog.log']

In that example I'm using the -c command, in case you want to understand why:

Quoting from man bash:

   -c string If the -c option is present,  then  commands  are  read  from
             string.   If  there  are arguments after the string, they are
             assigned to the positional parameters, starting with $0.

Let me know if it works for you.


问:
While executing mysql insert select query- can we do condition check?
I am trying to execute mysql select insert query as below.

```<code>INSERT INTO ACCOUNTS.TABLE1 (NAME,ID,STARTTIME,ENDTIME) SELECT NAME,ID,CREATIONTIME,EXPIRYTIME FROM ACCOUNTS.TABLE2 WHERE ...;
</code>```

Now, if EXPIRYTIME in table2 is null, then i want to update the ENDTIME in table1 to current timestamp. I have overriden the default behavior of this timestamp field by the description

```<code>ENDTIME TIMESTAMP NULL DEFAULT NULL
</code>```

for some reason.

Is it possible in the above select insert query to include some something like an if condition saying if (expirytime == null) then update endtime to current timestamp?

答:
Just select what you want:</p>

```<code>INSERT INTO ACCOUNTS.TABLE1 (NAME,ID,STARTTIME,ENDTIME)
SELECT NAME,ID,CREATIONTIME, ifnull(EXPIRYTIME, now())
FROM ACCOUNTS.TABLE2 WHERE ...;
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I am trying to execute mysql select insert query as below.

INSERT INTO ACCOUNTS.TABLE1 (NAME,ID,STARTTIME,ENDTIME) SELECT NAME,ID,CREATIONTIME,EXPIRYTIME FROM ACCOUNTS.TABLE2 WHERE ...;

Now, if EXPIRYTIME in table2 is null, then i want to update the ENDTIME in table1 to current timestamp. I have overriden the default behavior of this timestamp field by the description

ENDTIME TIMESTAMP NULL DEFAULT NULL

for some reason.

Is it possible in the above select insert query to include some something like an if condition saying if (expirytime == null) then update endtime to current timestamp?

Body:
Just select what you want:

INSERT INTO ACCOUNTS.TABLE1 (NAME,ID,STARTTIME,ENDTIME)
SELECT NAME,ID,CREATIONTIME, ifnull(EXPIRYTIME, now())
FROM ACCOUNTS.TABLE2 WHERE ...;


问:
Multiprocessing - Pipe vs Queue
What are the fundamental differences between queues and pipes in Python's multiprocessing package?

In what scenarios should one choose one over the other?  When is it advantageous to use Pipe()?  When is it advantageous to use Queue()?

答:
One additional feature of Queue() that is worth noting is the feeder thread. This section notes "When a process first puts an item on the queue a feeder thread is started which transfers objects from a buffer into the pipe." An infinite number of (or maxsize) items can be inserted into Queue() without any calls to queue.put() blocking. This allows you to store multiple items in a Queue(), until your program is ready to process them.

Pipe(), on the other hand, has a finite amount of storage for items that have been sent to one connection, but have not been received from the other connection. After this storage is used up, calls to connection.send() will block until there is space to write the entire item. This will stall the thread doing the writing until some other thread reads from the pipe. Connection objects give you access to the underlying file descriptor. On *nix systems, you can prevent connection.send() calls from blocking using the os.set_blocking() function. However, this will cause problems if you try to send a single item that does not fit in the pipe's file. Recent versions of Linux allow you to increase the size of a file, but the maximum size allowed varies based on system configurations. You should therefore never rely on Pipe() to buffer data. Calls to connection.send could block until data gets read from the pipe somehwere else.

In conclusion, Queue is a better choice than pipe when you need to buffer data. Even when you only need to communicate between two points.

Title: Multiprocessing - Pipe vs Queue


问:
Print out int[][] array using streams
I have a method rotateImage that returns an int[][] array, I am having trouble understaing how to display the actual values of the array instead of just the hashcode:

[I@548c4f57
[I@1218025c
[I@816f27d
```

<p>I tried doing this: </p>

```Arrays.stream(rotateImage(matrix)).forEach(System.out::println);
```

but that only returns the hashcode, not the actual numbers themselves. I also tried using to Arrays.toString() method in several ways but always get an error.

答:
It's cause you're accessing the address and not the actual values. You can simply do a lambda function and iterate through each row</p>

```<code>Arrays.stream(rotateImage(matrix)).
         forEach(row -> {
             for(int i : row) {
                System.out.println(i);
             }
        });
</code>```

Title: Print out int[][] array using streams

Body:
I have a method rotateImage that returns an int[][] array, I am having trouble understaing how to display the actual values of the array instead of just the hashcode:

[I@548c4f57
[I@1218025c
[I@816f27d

I tried doing this:

Arrays.stream(rotateImage(matrix)).forEach(System.out::println);

but that only returns the hashcode, not the actual numbers themselves. I also tried using to Arrays.toString() method in several ways but always get an error.

Body:
It's cause you're accessing the address and not the actual values. You can simply do a lambda function and iterate through each row

Arrays.stream(rotateImage(matrix)).
         forEach(row -> {
             for(int i : row) {
                System.out.println(i);
             }
        });


问:
Need help adding an object to my array list, whenever it changes
It may sound confusing at first, but i got this code

```<code>const updateFav = (value, index) => {
  const tempData = _.cloneDeep(listProyectos);
  console.log(tempData);
  tempData[index].fav = value;
  setListProyectos(tempData);
};

const listaFavoritos = _.filter(listProyectos, item => item.fav);
const finalObject = listaFavoritos;//{[thisParam]:listaFavoritos};
</code>```

i got a flatlist with an array with several items inside, and a dropdown menu where i select an item and depending on the id, it'll match the items with id of the flatlist object, the thing is, the items in flat list will display switches, and the code from updateFav, will save the value from the switches, and the whole idea, is whenever i switch on an element from the flatlist, it'll save it in a ListProyectos array.

the _.filter will get rid of all the elements that DO NOT contain the fav: true

So here is the problem, whenever i change the item from the dropdown, and change the flatlist, the whole listProyectos array get's replaced and i only see the last change i did.

here is the code for the dropdown

```<code><ModalDropdown
  defaultValue={'Seleccionar'}
  onSelect={async (index, value) =>
    {
      await ParametersBusiness.GetInstance().getProjectClients(value);
      setListProyectos(DataManager.ResponseProjectClient);
    }
  }
  options={DataManager.ListCliente}
/>
</code>```

and here the flatlist

```<code><FlatList
  data={listProyectos}
  renderItem={({item, index}) => (
</code>```

images to show what the actual problem is

ok the so when i switch on that project from that client, it saves the project to a new object, everything is fine there, BUT.

notice when i select a different client and switch another project, ONLY the LAST one i switched is saved, instead of both

gif where i select many projects from different clients

答: React works with immutable arrays. You can only change a array if you replace it all. Take a look at this: https://blog.logrocket.com/immutability-in-react-ebe55253a1cc</p>

Body:
It may sound confusing at first, but i got this code

const updateFav = (value, index) => {
  const tempData = _.cloneDeep(listProyectos);
  console.log(tempData);
  tempData[index].fav = value;
  setListProyectos(tempData);
};

const listaFavoritos = _.filter(listProyectos, item => item.fav);
const finalObject = listaFavoritos;//{[thisParam]:listaFavoritos};

i got a flatlist with an array with several items inside, and a dropdown menu where i select an item and depending on the id, it'll match the items with id of the flatlist object, the thing is, the items in flat list will display switches, and the code from updateFav, will save the value from the switches, and the whole idea, is whenever i switch on an element from the flatlist, it'll save it in a ListProyectos array.

the _.filter will get rid of all the elements that DO NOT contain the fav: true

So here is the problem, whenever i change the item from the dropdown, and change the flatlist, the whole listProyectos array get's replaced and i only see the last change i did.

here is the code for the dropdown

<ModalDropdown
  defaultValue={'Seleccionar'}
  onSelect={async (index, value) =>
    {
      await ParametersBusiness.GetInstance().getProjectClients(value);
      setListProyectos(DataManager.ResponseProjectClient);
    }
  }
  options={DataManager.ListCliente}
/>

and here the flatlist

<FlatList
  data={listProyectos}
  renderItem={({item, index}) => (

images to show what the actual problem is

ok the so when i switch on that project from that client, it saves the project to a new object, everything is fine there, BUT.

notice when i select a different client and switch another project, ONLY the LAST one i switched is saved, instead of both

gif where i select many projects from different clients


问:
aspnet-codegenerator could not execute
I am following a basic TodoList API tutorial for .Net Core 3.1 SDK from the Microsoft docs. I have reached this point in the tutorial: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1&tabs=visual-studio-code#scaffold-a-controller

After gloabally installing the aspnet-codegenerator tool, making sure it is in the correct path 'User.dotnet\tools', trying older versions, restarting VScode and powershell, it still gives the following error:

"Could not execute because the specified command or file was not found.
Possible reasons for this include:
  * You misspelled a built-in dotnet command.
  * You intended to execute a .NET Core program, but dotnet-aspnet-codegenerator does not exist.
  * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be
found on the PATH."

I am attempting to scaffold a todo controller with the following command:
"dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers"

答:
Make sure you've added these NuGet packages to the project you are using as startup project.</p>

```<code>dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
</code>```

Title: aspnet-codegenerator could not execute

Body:
Make sure you've added these NuGet packages to the project you are using as startup project.

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design


问:
Java 8 ZonedDateTime format date
I am writing a code to get current date of British Summer Time.
I am stuck in converting the date in desired format using below code.

```<code>ZoneId zid = ZoneId.of("Europe/London");
ZonedDateTime lt = ZonedDateTime.now(zid);

// create a formatter
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
// apply format()
String value = lt.format(formatter);

System.out.println("value ="+value);
</code>```

I am getting the output as value =2020-06-01+02:00 which is fine as per written code. But I want output of format 01-JUN-20

What formatter shall I use to achieve this?
Also will 'Europe/London' give proper date while in DST & also while not in DST?
please help me in above 2 questions.

答:
tl;dr

```<code>ZonedDateTime
.now(
    ZoneId.of( "Europe/London" )
)
.format(
    DateTimeFormatter
    .ofPattern( "dd-MMM-uu" )
    .withLocale( Locale.UK )
)
.toUpperCase(
    Locale.UK
)
</code>```

See this code run live at IdeOne.com.

01-JUN-20

Details

You asked:

will 'Europe/London' give proper date while in DST & also while not in DST?

Yes, your code is correct. Passing a ZoneId to ZonedDateTime.now does account for any anomalies in wall-clock time, including the anomaly of Daylight Saving Time (DST). The result is a date and time-of-day as seen by people in that region when they look up at the calendar & clock on their respective wall.

You may find it interesting or useful to see that same moment in UTC, an offset from UTC of zero hours-minutes-seconds. Extract a Instant object by calling toInstant.

You said:

But I want output of format 01-JUN-20

Define a custom formatting pattern to match your desired output. Instantiate a DateTimeFormatter object.

Specify a Locale object to determine the human language and cultural norms in naming and abbreviating the month name.

```<code>Locale locale = Locale.UK ;  // Or Locale.US, etc.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uu" ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ) ;
</code>```

I do not know how to force all-uppercase in a DateTimeFormatter formatting pattern. Perhaps DateTimeFormatterBuilder might help; I don't know. As a workaround, you could simply call String.toUpperCase( Locale ).

```<code>Locale locale = Locale.US ;  // Or Locale.UK, etc.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uu" ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ).toUpperCase( locale ) ;
</code>```

Tips

I suggest you not hard-code a format such as that. Generally better to let java.time automatically localize for you by calling DateTimeFormatter.ofLocalizedDateTime.

And I further suggest avoiding the use of only two digits for year as that makes the output harder to read and creates ambiguity. Saving a few pixels or toner particles does not justify the confusion I have seen occur in businesses.

Consider using the standard ISO 8601 format for dates, if your users are amenable: YYYY-MM-DD. This format is easy to recognize, easy to process mentally (large-medium-small level of detail), and easy to read across cultures. The ISO 8601 formats are used by default in the java.time classes when generating/parsing text.

Title: Java 8 ZonedDateTime format date

Body:
I am writing a code to get current date of British Summer Time.
I am stuck in converting the date in desired format using below code.

ZoneId zid = ZoneId.of("Europe/London");
ZonedDateTime lt = ZonedDateTime.now(zid);

// create a formatter
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
// apply format()
String value = lt.format(formatter);

System.out.println("value ="+value);

I am getting the output as value =2020-06-01+02:00 which is fine as per written code. But I want output of format 01-JUN-20

What formatter shall I use to achieve this?
Also will 'Europe/London' give proper date while in DST & also while not in DST?
please help me in above 2 questions.

Body:
tl;dr

ZonedDateTime
.now(
    ZoneId.of( "Europe/London" )
)
.format(
    DateTimeFormatter
    .ofPattern( "dd-MMM-uu" )
    .withLocale( Locale.UK )
)
.toUpperCase(
    Locale.UK
)

See this code run live at IdeOne.com.

01-JUN-20

Details

You asked:

will 'Europe/London' give proper date while in DST & also while not in DST?

Yes, your code is correct. Passing a ZoneId to ZonedDateTime.now does account for any anomalies in wall-clock time, including the anomaly of Daylight Saving Time (DST). The result is a date and time-of-day as seen by people in that region when they look up at the calendar & clock on their respective wall.

You may find it interesting or useful to see that same moment in UTC, an offset from UTC of zero hours-minutes-seconds. Extract a Instant object by calling toInstant.

You said:

But I want output of format 01-JUN-20

Define a custom formatting pattern to match your desired output. Instantiate a DateTimeFormatter object.

Specify a Locale object to determine the human language and cultural norms in naming and abbreviating the month name.

Locale locale = Locale.UK ;  // Or Locale.US, etc.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uu" ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ) ;

I do not know how to force all-uppercase in a DateTimeFormatter formatting pattern. Perhaps DateTimeFormatterBuilder might help; I don't know. As a workaround, you could simply call String.toUpperCase( Locale ).

Locale locale = Locale.US ;  // Or Locale.UK, etc.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uu" ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ).toUpperCase( locale ) ;

Tips

I suggest you not hard-code a format such as that. Generally better to let java.time automatically localize for you by calling DateTimeFormatter.ofLocalizedDateTime.

And I further suggest avoiding the use of only two digits for year as that makes the output harder to read and creates ambiguity. Saving a few pixels or toner particles does not justify the confusion I have seen occur in businesses.

Consider using the standard ISO 8601 format for dates, if your users are amenable: YYYY-MM-DD. This format is easy to recognize, easy to process mentally (large-medium-small level of detail), and easy to read across cultures. The ISO 8601 formats are used by default in the java.time classes when generating/parsing text.


问:
How to merge flow and channel in Kotlin?
I need to create an API, it should be flow, which collects events. The problem is that these events may be from a channel (I need an analog for PublishSubject) and from a flow (which does a network request).

I also not sure if it's the best solution, so let me know if I can make it better.

What am I doing:

My api:

```<code>override val statusFlow = trackStatus()

private fun trackStatus(): Flow<State> = flow { ... }

private val deviceChannel = Channel<State>(CONFLATED)
</code>```

So statusFlow should return a flow from which I can receive data from both flow and channel.

I tried to convert the channel to flow by consumeAsflow, but it doesn't work.

I see a solution as

```<code>private fun trackStatus(): Flow<State> = flowOf(channel.toFlow(), flow).flattenMerge()
</code>```

What is the proper way to do it?

答:
```<code>private fun trackStatus() = merge(deviceChannel.recieveAsFlow(), trackStatus)
</code>```

Definition of merge()from the coroutines library is

```<code>/**
 * Merges the given flows into a single flow without preserving an order of elements.
 * All flows are merged concurrently, without limit on the number of simultaneously collected flows.
 *
 * ### Operator fusion
 *
 * Applications of [flowOn], [buffer], [produceIn], and [broadcastIn] _after_ this operator are fused with
 * its concurrent merging so that only one properly configured channel is used for execution of merging logic.
 */
@ExperimentalCoroutinesApi
public fun <T> merge(vararg flows: Flow<T>): Flow<T> = flows.asIterable().merge()
</code>```

Body:
I need to create an API, it should be flow, which collects events. The problem is that these events may be from a channel (I need an analog for PublishSubject) and from a flow (which does a network request).

I also not sure if it's the best solution, so let me know if I can make it better.

What am I doing:

My api:

override val statusFlow = trackStatus()

private fun trackStatus(): Flow<State> = flow { ... }

private val deviceChannel = Channel<State>(CONFLATED)

So statusFlow should return a flow from which I can receive data from both flow and channel.

I tried to convert the channel to flow by consumeAsflow, but it doesn't work.

I see a solution as

private fun trackStatus(): Flow<State> = flowOf(channel.toFlow(), flow).flattenMerge()

What is the proper way to do it?

Body:
private fun trackStatus() = merge(deviceChannel.recieveAsFlow(), trackStatus)

Definition of merge()from the coroutines library is

/**
 * Merges the given flows into a single flow without preserving an order of elements.
 * All flows are merged concurrently, without limit on the number of simultaneously collected flows.
 *
 * ### Operator fusion
 *
 * Applications of [flowOn], [buffer], [produceIn], and [broadcastIn] _after_ this operator are fused with
 * its concurrent merging so that only one properly configured channel is used for execution of merging logic.
 */
@ExperimentalCoroutinesApi
public fun <T> merge(vararg flows: Flow<T>): Flow<T> = flows.asIterable().merge()


问:
How to upload the SAME file in angular4
I was able to successfully  upload a file, but the problem now is it won't let me upload the same file twice. Here's my code:

```<code> <input type="file" (change)="onFileChange($event)" name="fileUploaded" value="Choose a File" accept=".xlsx, .xlsm">
</code>```

I found out that the onFileChange($event) won't fire since the listener I used is (change) and I'm not changing the file the I'm uploading. What can I do to sovle my problem? Thank you

EDIT: To give you context why would I want to do that, I want to upload an excel file then display its content to the page. But when I upload an excel file then edit its data inside using ms excel then save and upload it again, the new edits won't display on the page. The page still displays the old data.

Here's my code for the eventHandler:

```<code>data: AOA = [ [], [] ];
reader: FileReader = new FileReader();
onFileChange(evt: any) {
        /* wire up file reader */
        console.log("G");
        const target: DataTransfer = <DataTransfer>(evt.target);
        this.reader.onload = (e: any) => {
            /* read workbook */
            this.data = [ [], [] ];
            console.log(target.types);
            const bstr: string  = e.target.result;
            const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'});
            /* grab first sheet */
            const wsname: string = wb.SheetNames[0];
            const ws: XLSX.WorkSheet = wb.Sheets[wsname];
            /* save data */
            this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1}));
        }
            this.reader.readAsBinaryString(target.files[0]);
    }
</code>```

答:
Its sort of gets cached . so just make sure u are cleaning it before uploading the file so what u can do is give the value as empty and then upload the file</p>

```<code><input type ="file" #fileUpload style="visibility: hidden;" (change)="uploadResume($event)">
<button (click)="fileUpload.value='';fileUpload.click();">Upload</button>
</code>```

Title: How to upload the SAME file in angular4

Body:
I was able to successfully  upload a file, but the problem now is it won't let me upload the same file twice. Here's my code:

 <input type="file" (change)="onFileChange($event)" name="fileUploaded" value="Choose a File" accept=".xlsx, .xlsm">

I found out that the onFileChange($event) won't fire since the listener I used is (change) and I'm not changing the file the I'm uploading. What can I do to sovle my problem? Thank you

EDIT: To give you context why would I want to do that, I want to upload an excel file then display its content to the page. But when I upload an excel file then edit its data inside using ms excel then save and upload it again, the new edits won't display on the page. The page still displays the old data.

Here's my code for the eventHandler:

data: AOA = [ [], [] ];
reader: FileReader = new FileReader();
onFileChange(evt: any) {
        /* wire up file reader */
        console.log("G");
        const target: DataTransfer = <DataTransfer>(evt.target);
        this.reader.onload = (e: any) => {
            /* read workbook */
            this.data = [ [], [] ];
            console.log(target.types);
            const bstr: string  = e.target.result;
            const wb: XLSX.WorkBook = XLSX.read(bstr, {type: 'binary'});
            /* grab first sheet */
            const wsname: string = wb.SheetNames[0];
            const ws: XLSX.WorkSheet = wb.Sheets[wsname];
            /* save data */
            this.data = <AOA>(XLSX.utils.sheet_to_json(ws, {header: 1}));
        }
            this.reader.readAsBinaryString(target.files[0]);
    }

Body:
Its sort of gets cached . so just make sure u are cleaning it before uploading the file so what u can do is give the value as empty and then upload the file

<input type ="file" #fileUpload style="visibility: hidden;" (change)="uploadResume($event)">
<button (click)="fileUpload.value='';fileUpload.click();">Upload</button>


问:
How to toggle chevron down/up using attr, basesd on sibling toggle states?
I would like to have the span in the ahref rotate on click of it, and rotate it back to it's normal chevron down when the ul its targetting is hidden again.

here is my code (it is shopify, based on liquid loops, so here is the jquery and one of the sets of values, there are 3 more divs in the loop that I excluded) - I have the toggle of the ul (box) to show/hide, but now I just need to add/remove the class of "active-1" to toggle the chevron-down to rotate with css - however I can't seem to achieve this, on click it doesn't remove the class of "active-1" on the span when clicking on another .toggle value.

any guidance would be helpful. thank you!

```<code>    jQuery(document).ready(function($){
  $('.toggle').on('click', function(){
var targetBox = $(this).attr('target-box'); // Find the target box

    $('.box').not(targetBox).removeClass('shown');

    $(targetBox).toggleClass('shown'); // Toggle the current state of this one

  });
});

</code>```

```<code>
<div class="content-group">

    <a href="#" target-box="#box1" class="toggle js-no-transition">Color <span class="chevron-down"></span></a>
       <div class="box-wrapper">
      <ul class="box shown" id="box1">

            <li><label>Black

              <input type="checkbox" name="Color" value="Color_Black">

            </label></li>

            <li><label>Gold

              <input type="checkbox" name="Color" value="Color_Gold">

            </label></li>

            <li><label>Silver

              <input type="checkbox" name="Color" value="Color_Silver">

            </label></li>

      </ul>
       </div>

       </div>

</code>```

答:
You can do it like this:</p>

```<code> jQuery(document).ready(function($) {
    $('.toggle').on('click', function() {
       var targetBox = $(this).attr('target-box');
       $('.box').not(targetBox).removeClass('shown');
       $(targetBox).toggleClass('shown');
       $(".chevron-down.active-1").not($(this).find(".chevron-down")).removeClass("active-1");
       $(this).find(".chevron-down").toggleClass("active-1");
    });
 });
</code>```

Body:
I would like to have the span in the ahref rotate on click of it, and rotate it back to it's normal chevron down when the ul its targetting is hidden again.

here is my code (it is shopify, based on liquid loops, so here is the jquery and one of the sets of values, there are 3 more divs in the loop that I excluded) - I have the toggle of the ul (box) to show/hide, but now I just need to add/remove the class of "active-1" to toggle the chevron-down to rotate with css - however I can't seem to achieve this, on click it doesn't remove the class of "active-1" on the span when clicking on another .toggle value.

any guidance would be helpful. thank you!

    jQuery(document).ready(function($){
  $('.toggle').on('click', function(){
var targetBox = $(this).attr('target-box'); // Find the target box

    $('.box').not(targetBox).removeClass('shown');

    $(targetBox).toggleClass('shown'); // Toggle the current state of this one

  });
});

    Color

Black

              <input type="checkbox" name="Color" value="Color_Black">

Gold

              <input type="checkbox" name="Color" value="Color_Gold">

Silver

              <input type="checkbox" name="Color" value="Color_Silver">

Body:
You can do it like this:

 jQuery(document).ready(function($) {
    $('.toggle').on('click', function() {
       var targetBox = $(this).attr('target-box');
       $('.box').not(targetBox).removeClass('shown');
       $(targetBox).toggleClass('shown');
       $(".chevron-down.active-1").not($(this).find(".chevron-down")).removeClass("active-1");
       $(this).find(".chevron-down").toggleClass("active-1");
    });
 });


问:
How do I extract data from a website for a data table using python?
Im building tools for a business I am starting, and one of the tools I need is a live reader of scrap prices to put into my website as well as deciphering overhead/profit. How would I take that information and then put it into a live data table?

Very amateur programmer, but better to do it myself.

答: You can use flask and Beautiful Soup. With the flask you will be able to save the data after obtaining the information from the site after manipulating the html with beautiful soup.</p>


问:
Android Studio: how to increase the auto line wrap in the editor
I edited this question to include the Flutter community, cause a lot of you use Android Studio and if anyone knows the answer, it'll be one of you. Thanks.

The editor in Android Studio is auto wrapping lines at about 80 characters.

How can I increase this? (using version 4.0)

Cheers,

Paul

答:
Settings > Editor > Code Style > [Language] > Wrapping and Braces > Hard wrap at

Android Studio (as with all IDEs built off of the IntelliJ platform) formats each language according to different specifications, so you will need to change this for all the languages you are using. The default is usually 100 and the max is 999


问:
Extract multiple image links from a single div tag that has no class name
Hi I have this HTML code from a website: I want to be able to extract multiple images, I have cases where there is 3-4 images. How would I go about doing that?

```<code><div style="float: right;"><u>Chakra required:</u>
     <img src="https://naruto-arena.net/images/energy/energy_2.gif">
     <img src="https://naruto-arena.net/images/energy/energy_4.gif">
</div>
</code>```

My code:

```<code> chakras1 = soup.find_all("div")[42].img['src']
 print(chakras1)
</code>```

Result:
https://naruto-arena.net/images/energy/energy_2.gif

I only get the FIRST image but now the second one.

答:
To extract multiple images from within a tag, I personally stick to using for loops. So what I mean is once you find the div tag that you want to look within and say you call that chakras1, I would write the following:

```<code>    for img in chakras1.find_all("img"):
         print(img)
</code>```

For me the steps kind of go as follows:

find the specific tags you are looking for (img src)

see what tag those tags are within (

navigate through the HTML to that tag (using beautiful soup's .find or .find_all functions depending on what you want to use)

once you have navigated to the tag search within that tag for the tags you're really looking for.

One quick note, with this method, if you are looking through multiple div tags, you're also going to need to loop through those as well.

I hope this makes sense!

Body:
Hi I have this HTML code from a website: I want to be able to extract multiple images, I have cases where there is 3-4 images. How would I go about doing that?

Chakra required:

My code:

 chakras1 = soup.find_all("div")[42].img['src']
 print(chakras1)

Result:
https://naruto-arena.net/images/energy/energy_2.gif

I only get the FIRST image but now the second one.

Body:
To extract multiple images from within a tag, I personally stick to using for loops. So what I mean is once you find the div tag that you want to look within and say you call that chakras1, I would write the following:

    for img in chakras1.find_all("img"):
         print(img)

For me the steps kind of go as follows:

find the specific tags you are looking for (img src)

see what tag those tags are within (

navigate through the HTML to that tag (using beautiful soup's .find or .find_all functions depending on what you want to use)

once you have navigated to the tag search within that tag for the tags you're really looking for.

One quick note, with this method, if you are looking through multiple div tags, you're also going to need to loop through those as well.

I hope this makes sense!


问:
Trigger click event on keypress for any focused element
Is there a default way to trigger a click event anytime enter is pressed on a focused element?

What I am referencing is the differences from pressing enter while focused on a <button> vs. pressing enter while focused on a

 , etc. The <button> keypress enter triggers as expected. However,
 keypress enter does nothing. I believe you have to specifically write the event in for that keypress.

```<code>$('li').click(function() {
    //toggles something
});

$("li").keydown(function(e){
    if(e.which === 13){
        $(this).click();
    }
});
</code>```

答:
If the elements on your page already have click events, and are in the tab order, and you just want to make the enter key trigger a click on whichever element has focus for accessibility, try the following:

```<code><head>
  <script>
  function handleEnter(e){
    var keycode = (e.keyCode ? e.keyCode : e.which);
    if (keycode == '13') {
      document.activeElement.click();
    }
  }
  </script>
</head>

<body onkeypress="handleEnter(event)">
</code>```

This is especially useful for adding play/pause and making other image based controls accessible in banner ads made with Google Web Designer.

Body:
Is there a default way to trigger a click event anytime enter is pressed on a focused element?

What I am referencing is the differences from pressing enter while focused on a <button> vs. pressing enter while focused on a

 , etc. The <button> keypress enter triggers as expected. However,
 keypress enter does nothing. I believe you have to specifically write the event in for that keypress.

$('li').click(function() {
    //toggles something
});

$("li").keydown(function(e){
    if(e.which === 13){
        $(this).click();
    }
});

Body:
If the elements on your page already have click events, and are in the tab order, and you just want to make the enter key trigger a click on whichever element has focus for accessibility, try the following:

<head>
  <script>
  function handleEnter(e){
    var keycode = (e.keyCode ? e.keyCode : e.which);
    if (keycode == '13') {
      document.activeElement.click();
    }
  }
  </script>
</head>

<body onkeypress="handleEnter(event)">

This is especially useful for adding play/pause and making other image based controls accessible in banner ads made with Google Web Designer.


问:
Draw an SVG rectangle with gradientUnits="objectBoundingBox" on Canvas without using the built in transform function or changing the color stops?
Here is an SVG that has a linear gradient that uses objectBoundingBox gradientUnits:

```<code><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
      <stop offset="40%" stop-color="yellow" />
      <stop offset="50%" stop-color="black" />
      <stop offset="60%" stop-color="red" />
    </linearGradient>
  </defs>

  <rect x="10" y="10" width="20" height="10" fill="url('#myGradient')" />
</svg>
</code>```

I need to draw this on a Canvas.

I can draw the gradient on a Canvas if I use the transform method:

```<code>const canvas = document.getElementById('canvasBuiltInScale');
const ctx = canvas.getContext('2d');

function draw(x0, y0, x1, y1) {
  ctx.save();

  // create a square 1x1 gradient
  const gradient = ctx.createLinearGradient(0, 0, 1,  1);
  gradient.addColorStop(0.4, 'yellow');
  gradient.addColorStop(0.5, 'black');
  gradient.addColorStop(0.6, 'red');

  // scale it up to the size of the bbox
  const width = x1 - x0;
  const height = y1 - y0;

  ctx.transform(width, 0, 0, height, x0, y0);
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, 1, 1);
  ctx.restore();
}

draw(10, 10, 40, 30);
</code>```

But unfortunately the customer does not want me to use the transform method.

I can draw the same gradient on a Canvas with a home rolled scaling instead.

```<code>const canvas = document.getElementById('canvasHomeRolledScale');
const ctx = canvas.getContext('2d');

function draw(x0, y0, x1, y1) {
  const width = x1-x0;
  const height = y1-y0;

  // The problem is that with userSpace coordinates, the normal to the gradient vector from x0,y0 to x1,y1 will not go between x1,y0 and x0,y1
  // I perform a home baked geometric calculation to find the normal vector to [x1-x0, y1-y0] since its normal vector will pass through [x1-x0, y1-y0]
  const gradient = ctx.createLinearGradient(
    x0 + (width - height) / 2,
    y0 + (height - width) / 2,
    x0 + (width - height) / 2 + height,
    y0 + (height - width) / 2 + width
  );

  gradient.addColorStop(rescale(0.4), 'yellow');
  gradient.addColorStop(rescale(0.5), 'black');
  gradient.addColorStop(rescale(0.6), 'red');
  ctx.fillStyle = gradient;
  ctx.fillRect(x0, y0, width, height);

  // The normal vector calculated above has the right direction, but not the right amplitude.
  // Here I guy guessed that I could use pythagoras theorem to arrive at the correct scale
  function rescale(percent) {
    const max = Math.max(height, width)
    const min = Math.min(height, width)
    const f = (
      Math.sqrt(
        Math.pow(max, 2) + Math.pow(min, 2)
      ) /
      Math.sqrt(
        Math.pow(max, 2) + Math.pow(max, 2)
      )
    );
    const midPoint = 0.5;
    return midPoint - (midPoint-percent) * f
  }
}

draw(10, 10, 40, 30);
</code>```

But I am not allowed to change the percentage of the color stops.

The objection in both cases has been the valid objection that there ought to be a simpler more elegant solution to this problem. Hence, I ask the intelligent people in here if there is a solution that:

Does not use the transform method

Does not change the color stops

答:
If you are looking for a transformation of coordinates, this would do the trick:

const canvas = document.getElementById('canvasBuiltInScale');
const ctx = canvas.getContext('2d');

function tcoord(x0, y0, x1, y1){
  let xc = (x1 + x0) / 2;
  let yc = (y1 + y0) / 2;
  let dx = (x1 - x0) / 2;
  let dy = (y1 - y0) / 2;
  let rx0 = xc - dy;
  let ry0 = yc - dx;
  let rx1 = xc + dy;
  let ry1 = yc + dx;
  let result = [rx0,ry0,rx1,ry1];
  return result;
}

function draw(x0, y0, x1, y1) {
  ctx.save();
  let c = tcoord(x0, y0, x0 + x1, y0 + y1);
  const gradient = ctx.createLinearGradient(c[0], c[1], c[2],  c[3]);
  gradient.addColorStop(0.4, 'yellow');
  gradient.addColorStop(0.5, 'black');
  gradient.addColorStop(0.6, 'red');
  ctx.fillStyle = gradient;
  ctx.fillRect(x0, y0, x1, y1);
  ctx.restore();
}

draw(10, 10, 80, 60);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><canvas id="canvasBuiltInScale" width="300" height="300">
</canvas></code>```

For what it is worth, I find your transform solution way more elegant.

EDIT after comment

It stands to reason that if we change the start and end points of the gradient, we also need to transform the gradient steps. I have forked the fiddle with a solution ( https://jsfiddle.net/ftadpu3c/3/ ). It uses a new function called transformGradient. Since this transformation depends on the first one, there is one parameter that is calculated in tcoord. I also changed the style a little bit to make it more consistent. The third and fourth parameters passed to draw are a width and a height, rather than coordinates.

Edit 2
I was caught up in the notion that the distance of the transformed points to the center of the rectangle had to be maintained. Of course, that is not true. By choosing a suitable distance, it will not be necessary to transform the gradient. See second fork at https://jsfiddle.net/uwshL43f/

Body:
Here is an SVG that has a linear gradient that uses objectBoundingBox gradientUnits:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
      <stop offset="40%" stop-color="yellow" />
      <stop offset="50%" stop-color="black" />
      <stop offset="60%" stop-color="red" />
    </linearGradient>
  </defs>

  <rect x="10" y="10" width="20" height="10" fill="url('#myGradient')" />
</svg>

I need to draw this on a Canvas.

I can draw the gradient on a Canvas if I use the transform method:

const canvas = document.getElementById('canvasBuiltInScale');
const ctx = canvas.getContext('2d');

function draw(x0, y0, x1, y1) {
  ctx.save();

  // create a square 1x1 gradient
  const gradient = ctx.createLinearGradient(0, 0, 1,  1);
  gradient.addColorStop(0.4, 'yellow');
  gradient.addColorStop(0.5, 'black');
  gradient.addColorStop(0.6, 'red');

  // scale it up to the size of the bbox
  const width = x1 - x0;
  const height = y1 - y0;

  ctx.transform(width, 0, 0, height, x0, y0);
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, 1, 1);
  ctx.restore();
}

draw(10, 10, 40, 30);

But unfortunately the customer does not want me to use the transform method.

I can draw the same gradient on a Canvas with a home rolled scaling instead.

const canvas = document.getElementById('canvasHomeRolledScale');
const ctx = canvas.getContext('2d');

function draw(x0, y0, x1, y1) {
  const width = x1-x0;
  const height = y1-y0;

  // The problem is that with userSpace coordinates, the normal to the gradient vector from x0,y0 to x1,y1 will not go between x1,y0 and x0,y1
  // I perform a home baked geometric calculation to find the normal vector to [x1-x0, y1-y0] since its normal vector will pass through [x1-x0, y1-y0]
  const gradient = ctx.createLinearGradient(
    x0 + (width - height) / 2,
    y0 + (height - width) / 2,
    x0 + (width - height) / 2 + height,
    y0 + (height - width) / 2 + width
  );

  gradient.addColorStop(rescale(0.4), 'yellow');
  gradient.addColorStop(rescale(0.5), 'black');
  gradient.addColorStop(rescale(0.6), 'red');
  ctx.fillStyle = gradient;
  ctx.fillRect(x0, y0, width, height);

  // The normal vector calculated above has the right direction, but not the right amplitude.
  // Here I guy guessed that I could use pythagoras theorem to arrive at the correct scale
  function rescale(percent) {
    const max = Math.max(height, width)
    const min = Math.min(height, width)
    const f = (
      Math.sqrt(
        Math.pow(max, 2) + Math.pow(min, 2)
      ) /
      Math.sqrt(
        Math.pow(max, 2) + Math.pow(max, 2)
      )
    );
    const midPoint = 0.5;
    return midPoint - (midPoint-percent) * f
  }
}

draw(10, 10, 40, 30);

But I am not allowed to change the percentage of the color stops.

The objection in both cases has been the valid objection that there ought to be a simpler more elegant solution to this problem. Hence, I ask the intelligent people in here if there is a solution that:

Does not use the transform method

Does not change the color stops

Body:
If you are looking for a transformation of coordinates, this would do the trick:

const canvas = document.getElementById('canvasBuiltInScale');
const ctx = canvas.getContext('2d');

function tcoord(x0, y0, x1, y1){
  let xc = (x1 + x0) / 2;
  let yc = (y1 + y0) / 2;
  let dx = (x1 - x0) / 2;
  let dy = (y1 - y0) / 2;
  let rx0 = xc - dy;
  let ry0 = yc - dx;
  let rx1 = xc + dy;
  let ry1 = yc + dx;
  let result = [rx0,ry0,rx1,ry1];
  return result;
}

function draw(x0, y0, x1, y1) {
  ctx.save();
  let c = tcoord(x0, y0, x0 + x1, y0 + y1);
  const gradient = ctx.createLinearGradient(c[0], c[1], c[2],  c[3]);
  gradient.addColorStop(0.4, 'yellow');
  gradient.addColorStop(0.5, 'black');
  gradient.addColorStop(0.6, 'red');
  ctx.fillStyle = gradient;
  ctx.fillRect(x0, y0, x1, y1);
  ctx.restore();
}

draw(10, 10, 80, 60);

<canvas id="canvasBuiltInScale" width="300" height="300">
</canvas>

For what it is worth, I find your transform solution way more elegant.

EDIT after comment

It stands to reason that if we change the start and end points of the gradient, we also need to transform the gradient steps. I have forked the fiddle with a solution ( https://jsfiddle.net/ftadpu3c/3/ ). It uses a new function called transformGradient. Since this transformation depends on the first one, there is one parameter that is calculated in tcoord. I also changed the style a little bit to make it more consistent. The third and fourth parameters passed to draw are a width and a height, rather than coordinates.

Edit 2
I was caught up in the notion that the distance of the transformed points to the center of the rectangle had to be maintained. Of course, that is not true. By choosing a suitable distance, it will not be necessary to transform the gradient. See second fork at https://jsfiddle.net/uwshL43f/


问:
How to distinguish different responses from useFetch custom hook
Basically in my App.js, I need to call useFetch twice to display spinner/data/error for two tables.

How do I go about distinguish which spinner/data/error is for which table? Because in useEffect I'm returning
{ data, loading, error }, and in App.js, I'm getting the value like so const { data, loading, error } = useFetch(url_order, date). But I want const { data_table1, loading_table1, error_table1 } = useFetch(url_order, date) instead.

This is my useFetch custom hook

```<code>import { useState, useEffect } from "react";

export default function useFetch(url, date) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);

  useEffect(() => {
    const doFetch = async () => {
      setLoading(true);
      try {
        const res = await fetch(url);
        const json = await res.json;
        setData(json.result.result);
      } catch (error) {
        setError(true);
      }
      setLoading(false);
    };
    doFetch();
  }, [date]);

  return { data, loading, error };
}
</code>```

This is my App.js

```<code>import React from "react";
import useFetch from "./hooks/useFetch";
import OrderTable from "./OrderTable";
import IngredientTable from "./IngredientTable";

const App = () => {
  const { data, loading, error } = useFetch(url_order, date);
  const { data, loading, error } = useFetch(url_ingredient, date);

  return (
    <div>
      {loading ? (
        <BeatLoader css={override} color={"#36D7B7"} loading={loading} />
      ) : error ? (
        <h3>Failed to fetch data for Order's table</h3>
      ) : (
        <OrderTable data={data} />
      )}

      {loading ? (
        <BeatLoader css={override} color={"#36D7B7"} loading={loading} />
      ) : error ? (
        <h3>Failed to fetch data for Ingredient's table</h3>
      ) : (
        <IngredientTable data={data} />
      )}
    </div>
  );
};

export default App;
</code>```

答:
If you write:

```<code>const order_table = useFetch(url_order, date);
const ingedient_table = useFetch(url_ingredient, date);
</code>```

Now you can access:

```<code>order_table.data
order_table.error
order_table.loading

ingedient_table.data
ingedient_table.error
ingedient_table.loading
</code>```

Body:
Basically in my App.js, I need to call useFetch twice to display spinner/data/error for two tables.

How do I go about distinguish which spinner/data/error is for which table? Because in useEffect I'm returning
{ data, loading, error }, and in App.js, I'm getting the value like so const { data, loading, error } = useFetch(url_order, date). But I want const { data_table1, loading_table1, error_table1 } = useFetch(url_order, date) instead.

This is my useFetch custom hook

import { useState, useEffect } from "react";

export default function useFetch(url, date) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);

  useEffect(() => {
    const doFetch = async () => {
      setLoading(true);
      try {
        const res = await fetch(url);
        const json = await res.json;
        setData(json.result.result);
      } catch (error) {
        setError(true);
      }
      setLoading(false);
    };
    doFetch();
  }, [date]);

  return { data, loading, error };
}

This is my App.js

import React from "react";
import useFetch from "./hooks/useFetch";
import OrderTable from "./OrderTable";
import IngredientTable from "./IngredientTable";

const App = () => {
  const { data, loading, error } = useFetch(url_order, date);
  const { data, loading, error } = useFetch(url_ingredient, date);

  return (

      {loading ? (
        <BeatLoader css={override} color={"#36D7B7"} loading={loading} />
      ) : error ? (

Failed to fetch data for Order's table

      ) : (
        <OrderTable data={data} />
      )}

      {loading ? (
        <BeatLoader css={override} color={"#36D7B7"} loading={loading} />
      ) : error ? (

Failed to fetch data for Ingredient's table

      ) : (
        <IngredientTable data={data} />
      )}

  );
};

export default App;

Body:
If you write:

const order_table = useFetch(url_order, date);
const ingedient_table = useFetch(url_ingredient, date);

Now you can access:

order_table.data
order_table.error
order_table.loading

ingedient_table.data
ingedient_table.error
ingedient_table.loading


问:
Recursion error in R (Fibonacci sequence)
So I am trying to learn R on my own and am just working through the online tutorial. I am trying to code a recursive function that prints the first n terms of the Fibonacci sequence and can't get the code to run without the error:

Error in if (nterms <= 0) { : missing value where TRUE/FALSE needed

My code does ask me for input before entering the if else statement either which I think is odd as well. Below is my code any help is appreciated.

```<code>#Define the fibonacci sequence

recurse_fibonacci <- function(n) {
    # Define the initial two values of the sequence

    if (n <= 1){
        return(n)
    } else {

    # define the rest of the terms of the sequence using recursion
    return(recurse_fibonacci(n-1) + recurse_fibonacci(n-2))
    }
}

#Take input from the user
nterms = as.integer(readline(prompt="How many terms? "))

# check to see if the number of terms entered is valid
if(nterms <= 0) {
    print("please enter a positive integer")
} else {

    # This part actually calculates and displays the first n terms of the sequence
    print("Fibonacci Sequence: ")
    for(i in 0:(nterms - 1)){
        print(recurse_fibonacci(i))
    }
}
</code>```

答:
To make it work with Rscript replace

nterms = as.integer(readline(prompt="How many terms? "))

with

```<code>cat ("How many terms?")
nterms = as.integer (readLines ("stdin", n = 1))
</code>```

Then you can run it as Rscript fib.R, assuming that the code is in the file fib.R in the current working directory.

Otherwise, execute it with source ("fib.R") within an R shell.

Rscript does not operate in interactive mode and does not expect any input from the terminal. Check what interactive () returns in both the cases. Rscript will return FALSE as it is non-interactive, but the same function when run within an R shell (with source ()) it will be true.

?readline mentions that it cannot be used in non-interactive mode. Whereas readLines explicitely connect to stdin.

Body:
So I am trying to learn R on my own and am just working through the online tutorial. I am trying to code a recursive function that prints the first n terms of the Fibonacci sequence and can't get the code to run without the error:

Error in if (nterms <= 0) { : missing value where TRUE/FALSE needed

My code does ask me for input before entering the if else statement either which I think is odd as well. Below is my code any help is appreciated.

#Define the fibonacci sequence

recurse_fibonacci <- function(n) {
    # Define the initial two values of the sequence

    if (n <= 1){
        return(n)
    } else {

    # define the rest of the terms of the sequence using recursion
    return(recurse_fibonacci(n-1) + recurse_fibonacci(n-2))
    }
}

#Take input from the user
nterms = as.integer(readline(prompt="How many terms? "))

# check to see if the number of terms entered is valid
if(nterms <= 0) {
    print("please enter a positive integer")
} else {

    # This part actually calculates and displays the first n terms of the sequence
    print("Fibonacci Sequence: ")
    for(i in 0:(nterms - 1)){
        print(recurse_fibonacci(i))
    }
}

Body:
To make it work with Rscript replace

nterms = as.integer(readline(prompt="How many terms? "))

with

cat ("How many terms?")
nterms = as.integer (readLines ("stdin", n = 1))

Then you can run it as Rscript fib.R, assuming that the code is in the file fib.R in the current working directory.

Otherwise, execute it with source ("fib.R") within an R shell.

Rscript does not operate in interactive mode and does not expect any input from the terminal. Check what interactive () returns in both the cases. Rscript will return FALSE as it is non-interactive, but the same function when run within an R shell (with source ()) it will be true.

?readline mentions that it cannot be used in non-interactive mode. Whereas readLines explicitely connect to stdin.


问:
How to change animator states from a key press in Unity?
I am working on a small beat-em-up game as a summer project. I am stuck trying to change the sprite animation when a key is pressed.

Here is my code:

```<code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    Animator anim;
    void Start()
    {
        anim = gameObject.GetComponent<Animator>();
    }

    void Update()
    {
        if (this.anim.GetCurrentAnimatorStateInfo(0).IsName("Jotaro Idle"))
        {
            if (Input.GetKey(KeyCode.D))
                anim.SetTrigger("WalkRightfromIdle");
            else if (Input.GetKey(KeyCode.A))
                anim.SetTrigger("WalkLeftFromIdle");
        }
    }
}
</code>```

Here is a screenshot of my animator window (each transition is controlled by a trigger) : https://imgur.com/a/f93GrAn

Any help would be appreciated.

答: Try using anim.Play(...) instead of anim.SetTrigger(...).

Body:
I am working on a small beat-em-up game as a summer project. I am stuck trying to change the sprite animation when a key is pressed.

Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    Animator anim;
    void Start()
    {
        anim = gameObject.GetComponent<Animator>();
    }

    void Update()
    {
        if (this.anim.GetCurrentAnimatorStateInfo(0).IsName("Jotaro Idle"))
        {
            if (Input.GetKey(KeyCode.D))
                anim.SetTrigger("WalkRightfromIdle");
            else if (Input.GetKey(KeyCode.A))
                anim.SetTrigger("WalkLeftFromIdle");
        }
    }
}

Here is a screenshot of my animator window (each transition is controlled by a trigger) : https://imgur.com/a/f93GrAn

Any help would be appreciated.


问:
PHP custom sorting: Manual sorting an array based on specified keys
I have an array that looks like

```<code>$array = [
    //...
    'name' => ['value' => 'Raj KB'],
    'street' => ['value' => 'Street ABC'],
    'city' => ['value' => 'Dubai'],
    'country_id' => ['value' => 'UAE'],
    'region' => ['value' => 'DXB'],
    'region_id' => ['value' => 11],
    'zip_code' => ['value' => 12345],
    'city_id' => ['value' => 22],
    //...
];
</code>```

I would like to sort the array so that the keys country_id, region, region_id, city, city_id occur serially while preserving the position of others.

Expected Output

```<code> $array = [
    //...
    'name' => ['value' => 'Raj KB'],
    'street' => ['value' => 'Street ABC'],
    'country_id' => ['value' => 'UAE'],
    'region' => ['value' => 'DXB'],
    'region_id' => ['value' => 11],
    'city' => ['value' => 'Dubai'],
    'city_id' => ['value' => 22],
    'zip_code' => ['value' => 12345],
    //...
];
</code>```

I have tried as:

Trial #1

```<code>uksort($array, function ($a, $b) {

  $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
  if (isset($order[$a]) && isset($order[$b])) {
    return $order[$a] - $order[$b];
  } else {
    return 0;
  }
});

var_dump($array);
</code>```

Trial #2

```<code>uksort($array, function ($a, $b) {

  $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
  if (!isset($order[$a]) && !isset($order[$b])) {
    return 0;
  } elseif (!isset($order[$a])) {
    return 1;
  } elseif (!isset($order[$b])) {
    return -1;
  } else {
    return $order[$a] - $order[$b];

  }
});

var_dump($array);
</code>```

But the rest of the orders are not maintained anymore.
So I want those custom fields to appear in the same order without breaking the positions of others. For example, name should appear first, etc.

答:
PHP is using Quicksort, so you can't just return return senseful values for the elements you want to be sorted.
In my opinion it's a bad idea to use uksort here, because you would have to use the current indices of your array as values, but thats impossible because you can't access a copy of the old array from inside your compare-function. Also you would need to know on which index the first of your special values is.

So I would suggest to do sth like this, because I think it's impossible to do what you want with uksort:

```<code>function customSort($array)
{
    $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
    $keyArray = array();
    $sortedArray = array();
    foreach ($array as $i => $value) {
        $keyArray[] = $i;
    }
    $counter = 0;
    $hasStarted = false;
    $insertLater = array();
    for ($i = 0; $i < count($keyArray); $i++) {
        if ($hasStarted) {
            if ($counter < count($order)) {
                $sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];

                $counter++;
                if (!isset($order[$keyArray[$i]])) {
                    array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
                }
                continue;
            }
        }

        if (count($insertLater) > 0) {
            $itemToInsert = array_shift($insertLater);
            $sortedArray[$itemToInsert["key"]] = $itemToInsert["value"];

            if (!isset($order[$keyArray[$i]])) {
                array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
            }
            continue;
        }
        if (isset($order[$keyArray[$i]]) && !$hasStarted) {
            $sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];
            $hasStarted = true;
            $counter++;
            continue;
        }
        $sortedArray[$keyArray[$i]] = $array[$keyArray[$i]];
    }
    return $sortedArray;
}
It's may
</code>```

be not the best solution, but it works O(n).

Body:
I have an array that looks like

$array = [
    //...
    'name' => ['value' => 'Raj KB'],
    'street' => ['value' => 'Street ABC'],
    'city' => ['value' => 'Dubai'],
    'country_id' => ['value' => 'UAE'],
    'region' => ['value' => 'DXB'],
    'region_id' => ['value' => 11],
    'zip_code' => ['value' => 12345],
    'city_id' => ['value' => 22],
    //...
];

I would like to sort the array so that the keys country_id, region, region_id, city, city_id occur serially while preserving the position of others.

Expected Output

 $array = [
    //...
    'name' => ['value' => 'Raj KB'],
    'street' => ['value' => 'Street ABC'],
    'country_id' => ['value' => 'UAE'],
    'region' => ['value' => 'DXB'],
    'region_id' => ['value' => 11],
    'city' => ['value' => 'Dubai'],
    'city_id' => ['value' => 22],
    'zip_code' => ['value' => 12345],
    //...
];

I have tried as:

Trial #1

uksort($array, function ($a, $b) {

  $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
  if (isset($order[$a]) && isset($order[$b])) {
    return $order[$a] - $order[$b];
  } else {
    return 0;
  }
});

var_dump($array);

Trial #2

uksort($array, function ($a, $b) {

  $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
  if (!isset($order[$a]) && !isset($order[$b])) {
    return 0;
  } elseif (!isset($order[$a])) {
    return 1;
  } elseif (!isset($order[$b])) {
    return -1;
  } else {
    return $order[$a] - $order[$b];

  }
});

var_dump($array);

But the rest of the orders are not maintained anymore.
So I want those custom fields to appear in the same order without breaking the positions of others. For example, name should appear first, etc.

Body:
PHP is using Quicksort, so you can't just return return senseful values for the elements you want to be sorted.
In my opinion it's a bad idea to use uksort here, because you would have to use the current indices of your array as values, but thats impossible because you can't access a copy of the old array from inside your compare-function. Also you would need to know on which index the first of your special values is.

So I would suggest to do sth like this, because I think it's impossible to do what you want with uksort:

function customSort($array)
{
    $order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
    $keyArray = array();
    $sortedArray = array();
    foreach ($array as $i => $value) {
        $keyArray[] = $i;
    }
    $counter = 0;
    $hasStarted = false;
    $insertLater = array();
    for ($i = 0; $i < count($keyArray); $i++) {
        if ($hasStarted) {
            if ($counter < count($order)) {
                $sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];

                $counter++;
                if (!isset($order[$keyArray[$i]])) {
                    array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
                }
                continue;
            }
        }

        if (count($insertLater) > 0) {
            $itemToInsert = array_shift($insertLater);
            $sortedArray[$itemToInsert["key"]] = $itemToInsert["value"];

            if (!isset($order[$keyArray[$i]])) {
                array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
            }
            continue;
        }
        if (isset($order[$keyArray[$i]]) && !$hasStarted) {
            $sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];
            $hasStarted = true;
            $counter++;
            continue;
        }
        $sortedArray[$keyArray[$i]] = $array[$keyArray[$i]];
    }
    return $sortedArray;
}
It's may

be not the best solution, but it works O(n).


问:
Updating .NET Standard library to work with ASP.NET Core 2.2 and 3.0
I have a .NET Standard library shared between several web apps in our organization. Since all of them use the same scheme for authentication, the code was put into a sharable library. All of the web apps have been targeting netcoreapp2.2 and the library targets netstandard2.0. I have updated the first web app to netcoreapp3.0 and after doing so it failed on startup with this error:

System.MissingFieldException: Field not found:
  'Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme'.

Which was thrown from this line in an extension method the library:

services.AddAuthentication(IISDefaults.AuthenticationScheme);

This is what the .csproj file for the library originally looked prior to the update:

```<code><Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0</TargetFrameworks>
    <RootNamespace></RootNamespace>
    <AssemblyName></AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

</Project>
</code>```

And this worked for our ASP.NET Core 2.2 apps. After some modifications I got the ASP.NET Core 3.0 app to run after changing the library to this:

```<code><Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
    <RootNamespace></RootNamespace>
    <AssemblyName></AssemblyName>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

</Project>
</code>```

Is this the preferred/correct way of doing this, or is there something simpler? Should the library be using the Microsoft.NET.Sdk.Web SDK instead?

答:
We had this same issue migrating an authentication library built for .NET standard 2.0, being used in a .NET Core 2.1 application that we migrated to 3.1. We received the same error message about IISDefaults.AuthenticationScheme.

Based on your comment (thanks btw!) it looks like yes, they did change that value from a static readonly string to a const string, a breaking change to be sure, but not a welcome one (at least in the moment). I could not find this specifically mentioned anywhere in the migration documentation (as linked by @McKabue).

Here is the .NET Core 2.2 doc for this field:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.iisintegration.iisdefaults.authenticationscheme?view=aspnetcore-2.2

And here it is for .NET Core 3.0, when the switch was made to a const:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.iisintegration.iisdefaults.authenticationscheme?view=aspnetcore-3.0

The Fix

As you mentioned in your comment, simply replace IISDefaults.AuthenticationScheme with the string value "Windows", as that is what the field/const value was returning anyways. This sidesteps the compatibility issues between .NET Core 2.2 and .NET 3.0+, without much fuss.

History

Bing and I looked around for anything specific on this, and found a couple interesting things on Github about it.

https://github.com/dotnet/aspnetcore/issues/3838 - An issue with the value being a field not a const. Note Tratcher says:

It was a mistake. Yes we should change it but we can't until 3.0. You can use the actual value "Windows" as a workaround.

And then later, the pull request that changed it from a static readonly to a const:
https://github.com/dotnet/aspnetcore/pull/4342/files/6def4a71dcb45fdd07278c11698bf9595c193dd9

Body:
I have a .NET Standard library shared between several web apps in our organization. Since all of them use the same scheme for authentication, the code was put into a sharable library. All of the web apps have been targeting netcoreapp2.2 and the library targets netstandard2.0. I have updated the first web app to netcoreapp3.0 and after doing so it failed on startup with this error:

System.MissingFieldException: Field not found:
  'Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme'.

Which was thrown from this line in an extension method the library:

services.AddAuthentication(IISDefaults.AuthenticationScheme);

This is what the .csproj file for the library originally looked prior to the update:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0</TargetFrameworks>
    <RootNamespace></RootNamespace>
    <AssemblyName></AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

</Project>

And this worked for our ASP.NET Core 2.2 apps. After some modifications I got the ASP.NET Core 3.0 app to run after changing the library to this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
    <RootNamespace></RootNamespace>
    <AssemblyName></AssemblyName>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
    <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Graph" Version="1.17.0" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.4.0" />
  </ItemGroup>

</Project>

Is this the preferred/correct way of doing this, or is there something simpler? Should the library be using the Microsoft.NET.Sdk.Web SDK instead?


问:
Is there away to start a phones native Navigation tool from Flex 4.5?
I am building a mobile application in Flex 4.5 and from this app I would like to start the device's native navigation tool, like Google Navigation for example.

Is there a way to open the Navigation App using Flex 4.5?

答:
As far as I knew, there was no way to launch other applications from a mobile Flex App.

Some native apps can be opened using URLs.  It is, basically, the Flash Platform version of saying "Let the OS Handle it."  If you HTTP link to a video, for example, it may open in a native player or it may open in the browser.

You can open the native text messaging program using sms as the protocol.  As far as I know, there is no universal URL to open navigation services.

This post alludes to the fact that linking to maps.google.com will do it.

You can look into using the AIR Geolocation services APIs; but that is intended for in-app usage not launching other apps.


问:
Which Object Oriented design is a better pick when one subclass calls another?
In my scenario, we offer multiple plans to customers. (planA, planB, planC etc.) planA is lower than planB and planB is lower than planC. A customer can move from lower plan to higher plan but not vice-versa. If a customer is on planA and wants to 'activate' planB, then planA must be cancelled. Essentially, a plan can be 'activated' and 'deactivated'. I had 2 designs in mind.

```<code>interface Plan {
   activate();
   deactivate();
}
</code>```

This interface will be inherited by each plans' (planA, planB, planC, etc). The activate method would be inherited and look something like this:

```<code>activate() {
   Plan planToCancel = getLowerGradePlanToCancel()
   planToCancel.cancel();
   // perform business logic to activate plan.
}
</code>```

Option B is something similar to strategy pattern: I have 2 interfaces:

```<code>interface Activate {
  activate();
}

interface Deactivate {
  deactivate()
}
</code>```

Each of the plans will inherit those interfaces. Then my business logic would look something like this:

```<code>activatePlan(planName, planToDeactivate) {
  Activate activate = Factory.getActivateInstanceForPlan(planName);
  DeActivate dectivate = Factory.getActivateInstanceForPlan(planToDeactivate);
  deactivate.deactivate();
  activate.activate();
}
</code>```

Of the two designs which one is more appropriate (Object Oriented) and why ? The only thing in code that is likely to change is more plans will be added in future.

答:
You have 3 plans. Plan C can't go higher and similarly plan A can't go lower. Plan B can do both operations. Use one interface and put activate and deactivate methods there. You already mentioned that on option A. Use template pattern there to give an opportunity to change their behaviours for your plans. This will be appropriate if you will add another plans later on. This will help you a lot when you add another plans.

If you will have only three plans, then second option is more appropriate. Since you have only 3 plans and only one of them using activate and deactivate together, then you don't need to implement both of the methods, interfaces. This will decrease the dependencies of your code.

Pick the best choice for your case.

Body:
In my scenario, we offer multiple plans to customers. (planA, planB, planC etc.) planA is lower than planB and planB is lower than planC. A customer can move from lower plan to higher plan but not vice-versa. If a customer is on planA and wants to 'activate' planB, then planA must be cancelled. Essentially, a plan can be 'activated' and 'deactivated'. I had 2 designs in mind.

interface Plan {
   activate();
   deactivate();
}

This interface will be inherited by each plans' (planA, planB, planC, etc). The activate method would be inherited and look something like this:

activate() {
   Plan planToCancel = getLowerGradePlanToCancel()
   planToCancel.cancel();
   // perform business logic to activate plan.
}

Option B is something similar to strategy pattern: I have 2 interfaces:

interface Activate {
  activate();
}

interface Deactivate {
  deactivate()
}

Each of the plans will inherit those interfaces. Then my business logic would look something like this:

activatePlan(planName, planToDeactivate) {
  Activate activate = Factory.getActivateInstanceForPlan(planName);
  DeActivate dectivate = Factory.getActivateInstanceForPlan(planToDeactivate);
  deactivate.deactivate();
  activate.activate();
}

Of the two designs which one is more appropriate (Object Oriented) and why ? The only thing in code that is likely to change is more plans will be added in future.