胡渣熟男

文章 评论 浏览 29

胡渣熟男 2025-02-21 00:55:23

使用filter选择列,然后使用重命名将“组”字符串替换为“预期销售”:

df1 = (df.filter(like='Group').mul(df['Price'], axis=0)
         .rename(columns=lambda x: x.replace('Group', 'Expected Sales')))
out = pd.concat([df, df1], axis=1)

输出:

>>> out

   Group A  Group B  Group C    Fruit  Price  Other  Expected Sales A  Expected Sales B  Expected Sales C
0        3        5      7.0   apples    1.0  blah1               3.0               5.0               7.0
1        2        4      6.0  bananas    0.5  blah2               1.0               2.0               3.0
2        5        8      9.2    pears    2.0  blah3              10.0              16.0              18.4

Use filter to select your columns then use rename to replace "Group" string by "Expected Sales":

df1 = (df.filter(like='Group').mul(df['Price'], axis=0)
         .rename(columns=lambda x: x.replace('Group', 'Expected Sales')))
out = pd.concat([df, df1], axis=1)

Output:

>>> out

   Group A  Group B  Group C    Fruit  Price  Other  Expected Sales A  Expected Sales B  Expected Sales C
0        3        5      7.0   apples    1.0  blah1               3.0               5.0               7.0
1        2        4      6.0  bananas    0.5  blah2               1.0               2.0               3.0
2        5        8      9.2    pears    2.0  blah3              10.0              16.0              18.4

熊猫:如何在多个列上执行相同的计算,这来自传递列表?

胡渣熟男 2025-02-20 17:26:46

我像这个

脚本

    var data = JSON.parse(request.responseText, function(key, x) {
        if (key === "flavor_profiles") {
           x = x.split(',');
        return x;
        }
        return x;
     });

一样解决了它。jshtml

<ul class="tags">
     {{#each flavor_profiles}}
     <li><a href="#" class="tag">{{this}}</a></li>
     {{/each}}
</ul>

I solved it like this

script.js

    var data = JSON.parse(request.responseText, function(key, x) {
        if (key === "flavor_profiles") {
           x = x.split(',');
        return x;
        }
        return x;
     });

HTML

<ul class="tags">
     {{#each flavor_profiles}}
     <li><a href="#" class="tag">{{this}}</a></li>
     {{/each}}
</ul>

车把 - 在{{{每个}}中划分字符串和迭代

胡渣熟男 2025-02-20 07:23:19

我想这是意见问题和权衡。

我赞成没有在表定义中定义的检查并在应用程序级别上执行的检查,以避免重复逻辑并提高可维护性(CF单个责任原则)。

对于字段有效性的内容,例如一个数字在范围内左右,我倾向于将这些数字定位在应用程序本身中,因为DB通常无法以精度验证它们(如何确保字符串是有效的电子邮件例如),并且在应用程序中使用所有检查也有助于构建一致的错误消息。

OTOH,DB是您唯一可以检查某些不变性的地方,例如某些列的Unicity,外国/主密钥关系的一致性,交易隔离,原子质...在并发和分布式设置中尤其如此:数据库是系统中唯一一致的部分,因此“知道足够”可以进行一些检查。

另外,数据库所能完成的所有工作都是您不必重新实现应用程序的逻辑,并且DB的代码通常经常进行测试=&gt;您可以选择将大量委派给数据库,以保持应用程序代码精益。

有人说,您不应过多地依赖DB的特定特定功能,并通过某些抽象界面将其从应用程序中脱离式功能,尽管我经常不同意:供应商特定的DB功能(例如示例中的特定检查)通常是该数据库所在的大部分添加值,而在20年的软件工程中,我几乎从未遇到过神话般的情况,在这种情况下,一个项目决定将其DB供应商交换为另一个(或他们做到了,他们确实从某些特定功能中受益=&gt;

简而言之:

  • 确保在整体上仅在一个地方定义每个逻辑,
  • 让您的数据库尽其所能,并尝试使您的代码很大一部分从事业务增值功能,而不是技术性的东西,
  • 这都是一种贸易 -真的,只要选择一种哲学,就接受它的侧面:)

I guess it's a matter of opinion and trade off.

I favor not having checks defined both in the table definitions and performed on the application level, to avoid the duplication of the logic and improve maintainability (cf single responsibility principle).

For the field validity stuff, like a number being within a range or so, I tend to position those in the app itself, because the DB is often not capable to validate them all with precision (how to make sure a string is a valid email for example), and having all the checks in app also helps build consistent error messages.

OTOH, the DB is the only place where you can check for some invariants, like unicity of some column, consistency of the foreign/primary key relationship, transaction isolation, atomicity... This is especially true in a concurrent and distributed setting: the DB is the only part of the system that is strongly consistent, and therefore "knows enough" to do some of the checks.

Also, all the work that the DB can do is logic that you don't have to re-implement in your app, and the code of the DB is often battled-tested => you can choose to delegate a lot to your DB in order to keep your application code lean.

Some say that you should not depend too much on vendor-specific features of your DB and de-couple it from your application via some abstract interface, although I often disagree with that: vendor-specific DB features (like specific checks in your example) are usually where most of the added-value of that DB lies, and in 20 years of software engineering I've almost never encountered the mythical situation where a project decided to swap their DB vendor for another (or when they did, they precisely did it to benefit from some specific features => the abstraction was in the way and had to be refactored or removed, without providing any protection nor benefit).

In short:

  • make sure each piece of logic is defined in only one place overall
  • let your DB do all it's good at, and try to have a large proportion of your code doing business value-added stuff instead of technical stuff
  • it's all a trade-off really, just pick a philosophy and accept its down-sides :)

创建桌子/设计的良好设计实践

胡渣熟男 2025-02-20 03:38:53

问题是拼字图投影和视图空间坐标:

  gluortho2d(0,w,h,0);
 

在此投影中,左上坐标为(0,0),右下是(wh),因此中心为(w/2)h/2),取决于视图的大小。由于对象的坐标没有更改,因此它不再在场景的中心中,因为对象的坐标仍然是旧中心(old_w/2old_h/code old_h/2 )。

使用中心为(0,0)的投影:

gluOrtho2D(-w/2, w/2, h/2, -h/2);

当然,现在您需要为场景中的对象指定不同的坐标。例如(0,0)中心。

如果您想保持场景,则需要保留投影。只需更改视口(glviewport(0,0,W,H)),但不要更改投影(删除gluortho2d(0,w,w,h,0)) 。

The problem is the orthographic projection and the view space coordinates:

gluOrtho2D(0, w, h, 0);

In this projection, the upper left coordinate is (0, 0) and the lower right is (w, h), so the center is (w/2, h/2), which depends on the size of the view. Since the object's coordinate has not changed, it is no longer in the center of the scene, since the object's coordinate is still the old center (old_w/2, old_h/2).

Use a projection where the center is (0, 0):

gluOrtho2D(-w/2, w/2, h/2, -h/2);

Of course, now you need to specify different coordinates for your objects in the scene. e.g. (0, 0) for the center.

If you want to keep the scene as is, you need to keep the projection. Just change the viewport (glViewport(0, 0, w, h)) but don't change the projection (remove gluOrtho2D(0, w, h, 0)).

调整大小opengl / glut之后的中心视口

胡渣熟男 2025-02-20 03:36:46

我只是添加答案,因为我还不能写任何评论,尽管我在CSS上并不陌生...

是的,您可以使用Flexbox,但我也会添加CSS网格,因为两者的组合都可以给您如果您打算制作更大的图表……

一旦使其正常工作,则更加灵活性,它很容易使用...

复制并将此代码粘贴到代码编辑器中并将其显示在您的浏览器中。

(如果使用VSCODE,则可以使用Liveserver扩展名)

,然后转到浏览器内部的开发工具(Ctrl+Shift+i),然后单击图标选择一个元素(在非常左侧的顶部)。

然后,在第一个Div内,您将看到带有网格单词的标签,单击它,然后在屏幕上看到网格。

最后,您只需要像那些旧战舰游戏之一或2D笛卡尔坐标系统一样填充行和列。

请记住,将物品放在网格上时,最好使用行而不是行和列的区域,因为这样更容易理解。

例如,在这种情况下,Connector 1从垂直线9到垂直线10,或第一个图填充第5行和第9行之间的空间,依此类推。

希望它有帮助!

顺便说一句,我更改了颜色,因为说明更容易。HTML

<!DOCTYPE html>
<html lang="en">
<head>

  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Document</title>

</head>
  <body>
  
      <!-- GRID FLOWCHART -->
      <div class="flowchart">

        <!-- FIRST FIGURE -->
        <div class="set" id="set1">
          <div class="box"><p>alpha</p></div>
      </div>

      <!-- FIRST CONNECTOR -->
      <div class="connector" id="connector1"></div>

      <!-- SECOND FIGURE -->
      <div class="set" id="set2">
        <div class="box"><p>beta</p></div>
        <div class="box"><p>gamma</p></div>
        <div class="box"><p>delta</p></div>
      </div>
      <!-- SECOND CONNECTOR -->
      <div class="connector" id="connector2"></div>

      <!-- THIRD FIGURE -->
      <div class="set" id="set3">
        <div class="box"><p>gamma</p></div>
      </div>

    </div>


  </body>
</html>

CSS:

body {
  width: 100vw;
  height: 100vh;
  background-color: #d3d3d3;
}

/* ****** GENERIC SHAPES : ********** */

.flowchart {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  grid-template-rows: repeat(12, 1fr);
  width: fit-content;
  height: fit-content;
  grid-gap: 2px;
}

.set {
  min-width: 100px;
  min-height: 100px;
  border: 2px dashed blue;
  border-radius: 15px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.box {
  width: 80%;
  height: 15%;
  background-color: rgb(255, 255, 255);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: 4%;
  padding: 6%;
  border: 1px solid black;
  /* border-radius: 5px; */
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  font-size: 0.9em;
}

.connector {
  width: 120%;
  max-height: 3px;
  background-color: black;
  transform: translateX(-6%);
}

/* ************* FIGURES : ************* */

#set1 {
  grid-column: 5/9;
  grid-row: 5/12;
}
#set2 {
  grid-column: 10/14;
  grid-row: 5/12;
}
#set3 {
  grid-column:15/19;
  grid-row: 5/12;
}


/* ******** CONNECTORS : *********** */

#connector1 {
  grid-column: 9/10;
  grid-row: 8/9;
}

#connector2 {
  grid-column: 14/15;
  grid-row: 8/9;
}

I'll just add an answer because I can't write any comments yet, although I'm not new at CSS...

Yes, you can use Flexbox but I will also add CSS Grid, as the combination of both can give you more flexibility if you're planning on making bigger charts...

Once you get it working, it's pretty easy to use...

Copy and paste this code in your code editor and display it in your browser.

( if you use VSCode you can use the liveServer extension)

Then go to the dev tools inside your browser (Ctrl+Shift+i) and click the icon to select an element (the one on top at the very left hand side).

Then, inside the first div, you will see a label with the word grid, click it and you'll see the grid on your screen.

Finally, you just have to fill the rows and columns with the figures as in one of those old battleship games, or a 2D Cartesian Coordinate System.

Keep in mind that when placing your items on the Grid, it's better to use the lines instead of the areas of the rows and columns, as it's much easier to understand it this way.

flowchart & CSS Grid positioning

So for instance, in this case, connector1 goes from vertical line 9 to vertical line 10, or the first figure fills the space between line 5 and line 9, and so on.

Hope it helps!

By the way, I changed colours as it's easier for the explanation..

HTML :

<!DOCTYPE html>
<html lang="en">
<head>

  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <title>Document</title>

</head>
  <body>
  
      <!-- GRID FLOWCHART -->
      <div class="flowchart">

        <!-- FIRST FIGURE -->
        <div class="set" id="set1">
          <div class="box"><p>alpha</p></div>
      </div>

      <!-- FIRST CONNECTOR -->
      <div class="connector" id="connector1"></div>

      <!-- SECOND FIGURE -->
      <div class="set" id="set2">
        <div class="box"><p>beta</p></div>
        <div class="box"><p>gamma</p></div>
        <div class="box"><p>delta</p></div>
      </div>
      <!-- SECOND CONNECTOR -->
      <div class="connector" id="connector2"></div>

      <!-- THIRD FIGURE -->
      <div class="set" id="set3">
        <div class="box"><p>gamma</p></div>
      </div>

    </div>


  </body>
</html>

CSS :

body {
  width: 100vw;
  height: 100vh;
  background-color: #d3d3d3;
}

/* ****** GENERIC SHAPES : ********** */

.flowchart {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  grid-template-rows: repeat(12, 1fr);
  width: fit-content;
  height: fit-content;
  grid-gap: 2px;
}

.set {
  min-width: 100px;
  min-height: 100px;
  border: 2px dashed blue;
  border-radius: 15px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.box {
  width: 80%;
  height: 15%;
  background-color: rgb(255, 255, 255);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: 4%;
  padding: 6%;
  border: 1px solid black;
  /* border-radius: 5px; */
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  font-size: 0.9em;
}

.connector {
  width: 120%;
  max-height: 3px;
  background-color: black;
  transform: translateX(-6%);
}

/* ************* FIGURES : ************* */

#set1 {
  grid-column: 5/9;
  grid-row: 5/12;
}
#set2 {
  grid-column: 10/14;
  grid-row: 5/12;
}
#set3 {
  grid-column:15/19;
  grid-row: 5/12;
}


/* ******** CONNECTORS : *********** */

#connector1 {
  grid-column: 9/10;
  grid-row: 8/9;
}

#connector2 {
  grid-column: 14/15;
  grid-row: 8/9;
}

如何在CSS中创建流程图

胡渣熟男 2025-02-20 02:55:22

我设法自己弄清楚了。

这是我为外面的任何人提供的Exec-Maven-plug + JIB CLI解决方案。

要测试粘贴,请将其调整到您的环境中,然后运行MVN Clean Package -P Local

pom.xml来自多模块设置,因此您可能必须重构或省略&lt; parent&gt;&gt;&gt;/parent&gt;标签以适合您需要。

它的作用:

  • 清洁目标目录
  • 将您的源文件编译到目标目录
  • 中的目标目录中的类中
  • ,重新包装类,libs,libs, 爆炸式 form form(用于更好的层缓存)正确地进入Spring Boot的非标准boot-inf输出目录
  • docker builddocker push通过引擎盖下方穿过jib cli
  • 在结尾处执行docker pull(出于调试目的),
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <artifactId>redacted</artifactId>
    <groupId>com.redacted</groupId>
    <version>0.0.1</version>
  </parent>

  <artifactId>sm-test</artifactId>
  <version>0.0.1</version>
  <name>test</name>
  <description>test</description>
  <packaging>jar</packaging>

  <properties>
    <profile.name>default</profile.name>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <mainClass>com.redacted.smtest.SmTestApplication</mainClass>
    <java.server.user>0:0</java.server.user>
    <java.to.image.tag>ghcr.io/redacted/${project.artifactId}:${project.version}-${profile.name}</java.to.image.tag>
    <java.from.image.tag>openjdk:11.0.14-jre@sha256:e2e90ec68d3eee5a526603a3160de353a178c80b05926f83d2f77db1d3440826</java.from.image.tag>
    <java.from.classpath>../target/${project.name}/${profile.name}/${project.build.finalName}.jar</java.from.classpath>
  </properties>

  <profiles>

    <!-- local -->
    <profile>
      <id>local</id>
      <properties>
        <profile.name>local</profile.name>
      </properties>
      <activation>
        <property>
          <name>noTest</name>
          <value>true</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>jib jar</id>
                <phase>package</phase>
                <goals>
                  <goal>exec</goal>
                </goals>
                <configuration>
                  <executable>jib</executable>
                  <workingDirectory>.</workingDirectory>
                  <skip>false</skip>
                  <arguments>
                    <argument>jar</argument>
                    <argument>--mode=exploded</argument>
                    <argument>--target=${java.to.image.tag}</argument>
                    <argument>--from=${java.from.image.tag}</argument>
                    <argument>--user=${java.server.user}</argument>
                    <argument>--creation-time=${maven.build.timestamp}</argument>
                    <argument>--jvm-flags=-Xms32m,-Xmx128m,-Dspring.profiles.active=default</argument>
                    <argument>${java.from.classpath}</argument>
                  </arguments>
                </configuration>
              </execution>
              <execution>
                <id>docker pull</id>
                <phase>install</phase>
                <goals>
                  <goal>exec</goal>
                </goals>
                <configuration>
                  <executable>docker</executable>
                  <workingDirectory>.</workingDirectory>
                  <skip>false</skip>
                  <arguments>
                    <argument>pull</argument>
                    <argument>${java.to.image.tag}</argument>
                  </arguments>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

  </profiles>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yworks</groupId>
      <artifactId>yguard</artifactId>
      <scope>compile</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>${project.name}</finalName>
    <directory>../target/${project.name}/${profile.name}/</directory>
    <outputDirectory>../target/${project.name}/${profile.name}/classes</outputDirectory>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <id>obfuscate</id>
            <phase>compile</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <tasks>

                <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                <!--suppress UnresolvedMavenProperty -->
                <taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="${runtime_classpath}"/>

                <mkdir dir="${project.build.directory}/obfuscated"/>

                <yguard>

                  <inoutpair in="${project.build.directory}/classes"
                             out="${project.build.directory}/obfuscated"/>

                  <externalclasses>
                    <!--suppress UnresolvedMavenProperty -->
                    <pathelement path="${runtime_classpath}"/>
                  </externalclasses>

                  <rename mainclass="${mainClass}"
                          logfile="${project.build.directory}/rename.log.xml"
                          scramble="true"
                          replaceClassNameStrings="true">

                    <property name="error-checking" value="pedantic"/>
                    <property name="naming-scheme" value="best"/>
                    <property name="language-conformity" value="compatible"/>
                    <property name="overload-enabled" value="true"/>

                    <!-- Generated by sm-test -->
                    <map>
                      <class map="d1e6064d$5a15$449b$a632$b2d967a61021" name="com.redacted.smtest.YGuardMappingRunner"/>
                    </map>

                  </rename>

                </yguard>

                <delete dir="${project.build.directory}/classes/com"/>

                <copy todir="${project.build.directory}/classes/com/" overwrite="true">
                  <fileset dir="${project.build.directory}/obfuscated/com/" includes="**"/>
                </copy>

                <delete dir="${project.build.directory}/obfuscated"/>

              </tasks>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <mainClass>${mainClass}</mainClass>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

cosciate jib.yaml jib> jib cli的文件

apiVersion: jib/v1alpha1
kind: BuildFile

workingDirectory: "/app"

entrypoint: ["java","-cp","/app/resources:/app/classes:/app/libs/*"]

layers:
  entries:
    - name: classes
      files:
        - properties:
            filePermissions: 755
          src: /classes
          dest: /app/classes

这是一个 必须编写一个小的抛出类来为Yguard的唯一类和软件包名称生成自定义映射(显然它无法自行完成):

package com.redacted.smtest;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

@Slf4j
@Component
public class YGuardMappingRunner implements CommandLineRunner {
  @Override
  public void run(String... args) throws Exception {
    if (args == null || args.length == 0)
      return;

    generateYGuardMapping(Path.of(args[0]));
  }

  void generateYGuardMapping(Path path) throws IOException {
    var packageSb = new StringBuilder();
    var classSb = new StringBuilder();

    mapPackages(path, packageSb);
    mapClasses(path, classSb);

    if (packageSb.length() > 0 && classSb.length() > 0)
      log.info(
          "\n<!-- Generated by sm-test -->\n<map>\n{}\n{}</map>",
          packageSb.toString(),
          classSb.toString());
    else if (packageSb.length() > 0 && classSb.length() == 0)
      log.info("\n<!-- Generated by sm-test -->\n<map>\n{}</map>", packageSb.toString());
    else if (packageSb.length() == 0 && classSb.length() > 0)
      log.info("\n<!-- Generated by sm-test -->\n<map>\n{}</map>", classSb.toString());
  }

  private void mapClasses(Path path, StringBuilder classSb) throws IOException {
    try (var stream = Files.walk(path, Integer.MAX_VALUE)) {
      stream
          .distinct()
          .filter(o -> o.getNameCount() >= 12)
          .filter(Files::isRegularFile)
          .map(o -> o.subpath(8, o.getNameCount()))
          .map(o -> o.toString().replace("\\", ".").replace(".java", ""))
          .filter(o -> !o.contains("Sm"))
          .sorted()
          .forEach(
              o ->
                  classSb.append(
                      String.format("%2s<class map=\"%s\" name=\"%s\"/>%n", "", getRandStr(), o)));
    }
  }

  private void mapPackages(Path path, StringBuilder packageSb) throws IOException {
    try (var stream = Files.walk(path, Integer.MAX_VALUE)) {
      stream
          .map(Path::getParent)
          .distinct()
          .filter(o -> o.getNameCount() >= 12)
          .map(o -> o.subpath(8, o.getNameCount()))
          .map(o -> o.toString().replace("\\", "."))
          .sorted()
          .forEach(
              o ->
                  packageSb.append(
                      String.format(
                          "%2s<package map=\"%s\" name=\"%s\"/>%n", "", getRandStr(), o)));
    }
  }

  private String getRandStr() {
    return UUID.randomUUID().toString().replaceAll("[-]+", "\\$");
  }
}

I managed to figure it out myself.

Here is my exec-maven-plug + jib cli solution for anyone out there.

To test paste it, adapt it to your environment, and run mvn clean package -P local.

This pom.xml is from a multi-module setup, so you may have to refactor or omit the <parent></parent> tag to suit you needs.

What it does:

  • Cleans target directory
  • Compiles your source files into the target directory
  • Obfuscates classes in the target directory
  • Repackages classes, libs, resources in exploded form (for better layer caching) correctly into Spring Boot's non-standard BOOT-INF output directory
  • Performs docker build, docker push under the hood through jib cli
  • Performs docker pull at the end (for debug purposes)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <artifactId>redacted</artifactId>
    <groupId>com.redacted</groupId>
    <version>0.0.1</version>
  </parent>

  <artifactId>sm-test</artifactId>
  <version>0.0.1</version>
  <name>test</name>
  <description>test</description>
  <packaging>jar</packaging>

  <properties>
    <profile.name>default</profile.name>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <mainClass>com.redacted.smtest.SmTestApplication</mainClass>
    <java.server.user>0:0</java.server.user>
    <java.to.image.tag>ghcr.io/redacted/${project.artifactId}:${project.version}-${profile.name}</java.to.image.tag>
    <java.from.image.tag>openjdk:11.0.14-jre@sha256:e2e90ec68d3eee5a526603a3160de353a178c80b05926f83d2f77db1d3440826</java.from.image.tag>
    <java.from.classpath>../target/${project.name}/${profile.name}/${project.build.finalName}.jar</java.from.classpath>
  </properties>

  <profiles>

    <!-- local -->
    <profile>
      <id>local</id>
      <properties>
        <profile.name>local</profile.name>
      </properties>
      <activation>
        <property>
          <name>noTest</name>
          <value>true</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>jib jar</id>
                <phase>package</phase>
                <goals>
                  <goal>exec</goal>
                </goals>
                <configuration>
                  <executable>jib</executable>
                  <workingDirectory>.</workingDirectory>
                  <skip>false</skip>
                  <arguments>
                    <argument>jar</argument>
                    <argument>--mode=exploded</argument>
                    <argument>--target=${java.to.image.tag}</argument>
                    <argument>--from=${java.from.image.tag}</argument>
                    <argument>--user=${java.server.user}</argument>
                    <argument>--creation-time=${maven.build.timestamp}</argument>
                    <argument>--jvm-flags=-Xms32m,-Xmx128m,-Dspring.profiles.active=default</argument>
                    <argument>${java.from.classpath}</argument>
                  </arguments>
                </configuration>
              </execution>
              <execution>
                <id>docker pull</id>
                <phase>install</phase>
                <goals>
                  <goal>exec</goal>
                </goals>
                <configuration>
                  <executable>docker</executable>
                  <workingDirectory>.</workingDirectory>
                  <skip>false</skip>
                  <arguments>
                    <argument>pull</argument>
                    <argument>${java.to.image.tag}</argument>
                  </arguments>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

  </profiles>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.yworks</groupId>
      <artifactId>yguard</artifactId>
      <scope>compile</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>${project.name}</finalName>
    <directory>../target/${project.name}/${profile.name}/</directory>
    <outputDirectory>../target/${project.name}/${profile.name}/classes</outputDirectory>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <id>obfuscate</id>
            <phase>compile</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <tasks>

                <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                <!--suppress UnresolvedMavenProperty -->
                <taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="${runtime_classpath}"/>

                <mkdir dir="${project.build.directory}/obfuscated"/>

                <yguard>

                  <inoutpair in="${project.build.directory}/classes"
                             out="${project.build.directory}/obfuscated"/>

                  <externalclasses>
                    <!--suppress UnresolvedMavenProperty -->
                    <pathelement path="${runtime_classpath}"/>
                  </externalclasses>

                  <rename mainclass="${mainClass}"
                          logfile="${project.build.directory}/rename.log.xml"
                          scramble="true"
                          replaceClassNameStrings="true">

                    <property name="error-checking" value="pedantic"/>
                    <property name="naming-scheme" value="best"/>
                    <property name="language-conformity" value="compatible"/>
                    <property name="overload-enabled" value="true"/>

                    <!-- Generated by sm-test -->
                    <map>
                      <class map="d1e6064d$5a15$449b$a632$b2d967a61021" name="com.redacted.smtest.YGuardMappingRunner"/>
                    </map>

                  </rename>

                </yguard>

                <delete dir="${project.build.directory}/classes/com"/>

                <copy todir="${project.build.directory}/classes/com/" overwrite="true">
                  <fileset dir="${project.build.directory}/obfuscated/com/" includes="**"/>
                </copy>

                <delete dir="${project.build.directory}/obfuscated"/>

              </tasks>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <mainClass>${mainClass}</mainClass>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

Here is an associate jib.yaml file for jib cli to work:

apiVersion: jib/v1alpha1
kind: BuildFile

workingDirectory: "/app"

entrypoint: ["java","-cp","/app/resources:/app/classes:/app/libs/*"]

layers:
  entries:
    - name: classes
      files:
        - properties:
            filePermissions: 755
          src: /classes
          dest: /app/classes

I also had to write a small throw-away class to generate custom mapping for unique class and package names for yGuard (apparently it cannot manage to do it on its own):

package com.redacted.smtest;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

@Slf4j
@Component
public class YGuardMappingRunner implements CommandLineRunner {
  @Override
  public void run(String... args) throws Exception {
    if (args == null || args.length == 0)
      return;

    generateYGuardMapping(Path.of(args[0]));
  }

  void generateYGuardMapping(Path path) throws IOException {
    var packageSb = new StringBuilder();
    var classSb = new StringBuilder();

    mapPackages(path, packageSb);
    mapClasses(path, classSb);

    if (packageSb.length() > 0 && classSb.length() > 0)
      log.info(
          "\n<!-- Generated by sm-test -->\n<map>\n{}\n{}</map>",
          packageSb.toString(),
          classSb.toString());
    else if (packageSb.length() > 0 && classSb.length() == 0)
      log.info("\n<!-- Generated by sm-test -->\n<map>\n{}</map>", packageSb.toString());
    else if (packageSb.length() == 0 && classSb.length() > 0)
      log.info("\n<!-- Generated by sm-test -->\n<map>\n{}</map>", classSb.toString());
  }

  private void mapClasses(Path path, StringBuilder classSb) throws IOException {
    try (var stream = Files.walk(path, Integer.MAX_VALUE)) {
      stream
          .distinct()
          .filter(o -> o.getNameCount() >= 12)
          .filter(Files::isRegularFile)
          .map(o -> o.subpath(8, o.getNameCount()))
          .map(o -> o.toString().replace("\\", ".").replace(".java", ""))
          .filter(o -> !o.contains("Sm"))
          .sorted()
          .forEach(
              o ->
                  classSb.append(
                      String.format("%2s<class map=\"%s\" name=\"%s\"/>%n", "", getRandStr(), o)));
    }
  }

  private void mapPackages(Path path, StringBuilder packageSb) throws IOException {
    try (var stream = Files.walk(path, Integer.MAX_VALUE)) {
      stream
          .map(Path::getParent)
          .distinct()
          .filter(o -> o.getNameCount() >= 12)
          .map(o -> o.subpath(8, o.getNameCount()))
          .map(o -> o.toString().replace("\\", "."))
          .sorted()
          .forEach(
              o ->
                  packageSb.append(
                      String.format(
                          "%2s<package map=\"%s\" name=\"%s\"/>%n", "", getRandStr(), o)));
    }
  }

  private String getRandStr() {
    return UUID.randomUUID().toString().replaceAll("[-]+", "\\
quot;);
  }
}

将Google Jib与Yguard集成

胡渣熟男 2025-02-19 16:05:45

下关闭并重新启动我的机器,它允许所有更新和恢复原状的生效,并解决了问题。

With closing down and rebooting my machine, it allowed for all updates and reinstallation's to take effect and the issue was solved.

使用ggplot,未加载在r控制台中的图

胡渣熟男 2025-02-19 09:17:24

您没有使用数组,因此所有以前的输入将被最后一个输入所取代。如果您没有更多的字段可随着请求发送,则可以通过将表格放入循环中来解决此问题。 按钮标签还接受一个值,因此您可以跳过隐藏的输入字段以使用较少的代码。

@foreach($features as $feature)
<tr>
    <td>{{ $feature->detail }}</td>
    <td>row</td>
    <td>
        <form action="{{route('sendDate')}}" method="post" >
            @csrf
            <button type="submit" name="ft" value="{{ $feature->detail }}" > insert</button>
        </form>
    </td>
</tr>
@endforeach

You are not using an array so all your previous inputs will be replaced by the last one. If you don't have any more fields to send with your request you can solve this by putting your form inside your loop. button tag also accepts a value so you can skip the hidden input field to use less code.

@foreach($features as $feature)
<tr>
    <td>{{ $feature->detail }}</td>
    <td>row</td>
    <td>
        <form action="{{route('sendDate')}}" method="post" >
            @csrf
            <button type="submit" name="ft" value="{{ $feature->detail }}" > insert</button>
        </form>
    </td>
</tr>
@endforeach

Laravel-插入选定的行

胡渣熟男 2025-02-19 02:42:12

我认为您选择的日期数据类型是int,这就是为什么您会遇到错误,即INT不是DateTime的子类型

DateTime? selectedDay = DateTime.now();

 //Here is Calendar widget
Calendar(
        initialDate: selectedDay,
        events: const {},
        startOnMonday: true,
        isExpandable: true,
        eventDoneColor: Colors.green,
        selectedColor: Colors.pink,
        todayColor: Colors.blue,
        eventColor: Colors.grey,
        onDateSelected: (date) {
          _handleNewDate(date);
        },
      ),

void _handleNewDate(date) {
 setState(() {
   selectedDay = date;
   // selectedEvent = events[selectedDay] ?? [];
   print(selectedDay);
 });
}

I think your selectedDay datatype is int that's why you getting error that int isn't the subtype of DateTime

DateTime? selectedDay = DateTime.now();

 //Here is Calendar widget
Calendar(
        initialDate: selectedDay,
        events: const {},
        startOnMonday: true,
        isExpandable: true,
        eventDoneColor: Colors.green,
        selectedColor: Colors.pink,
        todayColor: Colors.blue,
        eventColor: Colors.grey,
        onDateSelected: (date) {
          _handleNewDate(date);
        },
      ),

void _handleNewDate(date) {
 setState(() {
   selectedDay = date;
   // selectedEvent = events[selectedDay] ?? [];
   print(selectedDay);
 });
}

日历小部件ain&#x27; t正常工作

胡渣熟男 2025-02-18 18:19:31

如果您喜欢IFS,则可能需要这样调整(也应该以类似的方式使用HH:MM)

=IFS(G3<6;"Night Off Prime";G3<18;"Day Off Prime";G3<23;"Prime";TRUE;"Night Off Prime")

:设置)

另外:

=IFS(G3<0;"#N/A";G3<6;"Night Off Prime";G3<18;"Day Off Prime";G3<23;"Prime";G3<24;"Night Off Prime";TRUE;"#N/A")

If you prefer the IFS you may want to adjust like this (should work in the similar way for hh:mm as well):

=IFS(G3<6;"Night Off Prime";G3<18;"Day Off Prime";G3<23;"Prime";TRUE;"Night Off Prime")

(may replace ; with , depending on regional setting)

alternatively:

=IFS(G3<0;"#N/A";G3<6;"Night Off Prime";G3<18;"Day Off Prime";G3<23;"Prime";G3<24;"Night Off Prime";TRUE;"#N/A")

是否可以根据时间值来使用Excel函数来给出值?

胡渣熟男 2025-02-18 12:15:33

该行为是由于默认参数shuffle = true in model.fit(*)而不是错误。根据 docs >::

布尔值(是在每个时期之前将训练数据洗净)还是str(用于“批次”)。当x是tf.data.dataset的生成器或对象时,该参数将被忽略。 “批次”是处理HDF5数据局限性的特殊选择;它在批处理大小的块中散发。当steps_per_epoch不是一个时,没有效果。

因此,当传递tf.data.dataset时,此参数将被忽略,并且在每个时期之后,数据不会像其他数组中的其他方法一样重新封装。
这是获得两种方法相同结果的代码:

import numpy as np
import tensorflow as tf

tf.keras.utils.set_random_seed(0)

n_examples, n_dims = (100, 10)
raw_dataset = np.random.randn(n_examples, n_dims)

model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Dense(
            1024, activation="relu", use_bias=True
        ),
        tf.keras.layers.Dense(
            1, activation="linear", use_bias=True
        ),
    ]
)

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss="mse",
)

x_train = raw_dataset[:, :-1]
y_train = raw_dataset[:, -1]
dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))

n_epochs = 10
batch_size = 16

use_dataset = False
if use_dataset:
    model.fit(
        dataset.batch(batch_size=batch_size),
        epochs=n_epochs,
    )
else:
    model.fit(
        x=x_train,
        y=y_train,
        batch_size=batch_size,
        shuffle=False,
        epochs=n_epochs,
    )

print("Evaluation:")
model.evaluate(x_train, y_train)
model.evaluate(dataset.batch(batch_size=batch_size))

The behavior is due to the default parameter shuffle=True in model.fit(*) and not a bug. According to the docs regarding shuffle:

Boolean (whether to shuffle the training data before each epoch) or str (for 'batch'). This argument is ignored when x is a generator or an object of tf.data.Dataset. 'batch' is a special option for dealing with the limitations of HDF5 data; it shuffles in batch-sized chunks. Has no effect when steps_per_epoch is not None.

So this parameter is ignored when a tf.data.Dataset is passed, and the data is not reshuffled after each epoch as in the other approach with arrays.
Here is the code to get the same results for both methods:

import numpy as np
import tensorflow as tf

tf.keras.utils.set_random_seed(0)

n_examples, n_dims = (100, 10)
raw_dataset = np.random.randn(n_examples, n_dims)

model = tf.keras.models.Sequential(
    [
        tf.keras.layers.Dense(
            1024, activation="relu", use_bias=True
        ),
        tf.keras.layers.Dense(
            1, activation="linear", use_bias=True
        ),
    ]
)

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss="mse",
)

x_train = raw_dataset[:, :-1]
y_train = raw_dataset[:, -1]
dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))

n_epochs = 10
batch_size = 16

use_dataset = False
if use_dataset:
    model.fit(
        dataset.batch(batch_size=batch_size),
        epochs=n_epochs,
    )
else:
    model.fit(
        x=x_train,
        y=y_train,
        batch_size=batch_size,
        shuffle=False,
        epochs=n_epochs,
    )

print("Evaluation:")
model.evaluate(x_train, y_train)
model.evaluate(dataset.batch(batch_size=batch_size))

使用TF.Data.Dataset和Numpy阵列进行模型培训产生不同的结果

胡渣熟男 2025-02-18 03:25:46

呈现route> Route的组件,并且应调用组件:

<Route exact path="/" component={<HomeScreen/>}/>

它应该是element,而不是组件,该属性 用于React路由器DOM V5

It should be element, not component, that property that renders a component for a Route, and the component should be called:

<Route exact path="/" component={<HomeScreen/>}/>

What you have there is for React Router Dom v5.

反应路线不渲染

胡渣熟男 2025-02-18 02:14:14

我通过将整个数组转换为int来解决typeserror

chain = chain.astype(int)

I solved the typeError by converting the whole array to int

chain = chain.astype(int)

在阵列n时重复特定行

胡渣熟男 2025-02-17 20:57:36

我认为说特定实现的实用方法是“正确的方式™”,如果它仅是“正确”(“正确”),而“正确”的解决方案与“错误”解决方案相反 Tomáš的解决方案是对基于字符串的数组比较的明显改进,但这并不意味着它客观地“正确”。什么是正确?是最快的吗?它是最灵活的吗?是最简单的理解吗?调试是最快的吗?它使用最少的操作吗?它有任何副作用吗?没有一个解决方案可以拥有最好的一切。

托马斯(Tomáš)可以说他的解决方案很快,但我也想说这是不必要的复杂。它试图是一种适用于所有阵列的多合一解决方案。实际上,它甚至不仅接受数组作为输入,而且仍然试图给出一个“有效”的答案。


仿制药提供可重复性,

我的答案将以不同的方式解决问题。我将从一个通用arraycompare过程开始,该过程仅与踏上数组有关。从那里,我们将构建其他基本比较功能,例如arrayequalarraydeepequal等,

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

我认为最好的代码甚至不需要注释,这是也不例外。这里很少发生,您几乎没有努力就可以理解此过程的行为。当然,现在有些ES6语法对您来说似乎很陌生,但这仅仅是因为ES6相对较新。

正如类型所建议的那样,arraycompare采用比较函数,f,两个输入数组,xsys。在大多数情况下,我们要做的就是为输入数组中的每个元素调用f(x)(y)。如果用户定义f返回false> false - 感谢&amp;&amp;&amp;',我们返回早期false false 。短路评估。因此,是的,这意味着比较器可以尽早停止迭代,并在不需要的情况下阻止循环通过其余的输入阵列。


接下来,严格的比较

,使用我们的arraycompare函数,我们可以轻松创建可能需要的其他功能。我们将从基本array equal开始……

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

很简单。 arrayequal可以使用arraycompare和一个比较ab使用===的比较器函数进行定义。(严格平等)。

请注意,我们还将等于定义为其自己的功能。这突出了arraycompare作为高阶功能的作用,可以在另一种数据类型(array)的上下文中使用我们的一阶比较器。


松散的比较,

我们可以使用==而不是很容易地定义arrayloose equal。现在,当比较1(编号)与'1'(string)时,结果将为true

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

深层比较(递归

)可能注意到这只是比较。当然,Tomáš的解决方案是“正确的Way™”,因为它确实具有深入的比较,对吗?

好吧,我们的arraycompare过程的用途足够多,可以使深度平等测试变得轻而易举……

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

简单。我们使用 的高阶函数构建一个深层比较器。这次,我们使用自定义比较器包装arraycompare,该比较器将检查ab是数组。如果是这样,请重新申请arrayDeepCompare否则将Ab与用户指定的比较器(f)进行比较。这使我们能够将深层比较行为与实际比较单个元素进行比较分开。即,如上所述,我们可以使用等于, loode> soce> 或我们进行的任何其他比较器进行深入比较。

因为ArrayDeepCompare是咖喱的,所以我们可以像以前的示例中一样部分地应用它

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

,这已经对Tomáš的解决方案有了明显的改进或根据需要对我的阵列进行深入比较。


对象比较(示例)

现在,如果您有一系列对象或其他东西怎么办? 也许您要将这些数组视为“相等”

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

如果每个对象都具有相同的id值…简单, 。在这里,我使用了香草JS对象,但是这种类型的比较器可以适用于任何任何对象类型。甚至您的自定义对象。 Tomáš的解决方案是否需要完全重新设计,以支持具有对象的这种平等测试

深度测试?没问题。我们构建了高度通用的通用功能,因此它们将在各种用例中工作。

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

任意比较(例如)

,或者如果您想进行其他类型的完全任意的比较怎么办?也许我想知道每个x是否大于每个y……

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

更少的是

您可以看到我们实际上使用更少的代码做更多的事情。 arraycompare本身以及我们制作的每个自定义比较器都有一个非常简单的实现。

轻松地,我们可以准确地定义我们希望如何比较两个阵列 - 浅,深,严格,松散,某些对象属性或某些任意计算,或使用一个过程 - - >,<代码> arraycompare 。也许甚至梦想着regexp比较器!我知道孩子们如何爱那些言论……

这是最快的吗?没有。但这可能也不需要。如果速度是用于衡量代码质量的唯一度量,那么许多非常出色的代码就会被抛弃 - 这就是为什么我将这种方法称为实用方法。也许要更公平, a 实用的方式。此描述适合此答案,因为我并不是说这个答案与其他答案相比仅是实际的。客观上是正确的。我们的实用性很高,几乎没有易于推理的代码。没有其他代码可以说我们没有赢得此描述。

这是否使您成为您的“正确”解决方案?这是您的决定。没有其他人可以为您做到这一点;只有你知道自己的需求。在几乎所有情况下,我都将直接,实用和多才多艺的代码重视而不是聪明和快速的代码。您的价值可能会有所不同,因此请选择对您有用的东西。


编辑

我的旧答案更专注于将arrayequal分解为微小的过程。这是一个有趣的练习,但实际上并不是解决此问题的最佳(最实用)方法。如果您有兴趣,可以看到此修订历史记录。

The Practical Way

I think it's wrong to say a particular implementation is "The Right Way™" if it's only "right" ("correct") in contrast to a "wrong" solution. Tomáš's solution is a clear improvement over string-based array comparison, but that doesn't mean it's objectively "right". What is right anyway? Is it the fastest? Is it the most flexible? Is it the easiest to comprehend? Is it the quickest to debug? Does it use the least operations? Does it have any side effects? No one solution can have the best of all the things.

Tomáš's could say his solution is fast but I would also say it is needlessly complicated. It tries to be an all-in-one solution that works for all arrays, nested or not. In fact, it even accepts more than just arrays as an input and still attempts to give a "valid" answer.


Generics offer reusability

My answer will approach the problem differently. I'll start with a generic arrayCompare procedure that is only concerned with stepping through the arrays. From there, we'll build our other basic comparison functions like arrayEqual and arrayDeepEqual, etc

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

In my opinion, the best kind of code doesn't even need comments, and this is no exception. There's so little happening here that you can understand the behaviour of this procedure with almost no effort at all. Sure, some of the ES6 syntax might seem foreign to you now, but that's only because ES6 is relatively new.

As the type suggests, arrayCompare takes comparison function, f, and two input arrays, xs and ys. For the most part, all we do is call f (x) (y) for each element in the input arrays. We return an early false if the user-defined f returns false – thanks to &&'s short-circuit evaluation. So yes, this means the comparator can stop iteration early and prevent looping through the rest of the input array when unnecessary.


Strict comparison

Next, using our arrayCompare function, we can easily create other functions we might need. We'll start with the elementary arrayEqual

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

Simple as that. arrayEqual can be defined with arrayCompare and a comparator function that compares a to b using === (for strict equality).

Notice that we also define equal as it's own function. This highlights the role of arrayCompare as a higher-order function to utilize our first order comparator in the context of another data type (Array).


Loose comparison

We could just as easily defined arrayLooseEqual using a == instead. Now when comparing 1 (Number) to '1' (String), the result will be true

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

Deep comparison (recursive)

You've probably noticed that this is only shallow comparison tho. Surely Tomáš's solution is "The Right Way™" because it does implicit deep comparison, right ?

Well our arrayCompare procedure is versatile enough to use in a way that makes a deep equality test a breeze …

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

Simple as that. We build a deep comparator using another higher-order function. This time we're wrapping arrayCompare using a custom comparator that will check if a and b are arrays. If so, reapply arrayDeepCompare otherwise compare a and b to the user-specified comparator (f). This allows us to keep the deep comparison behavior separate from how we actually compare the individual elements. Ie, like the example above shows, we can deep compare using equal, looseEqual, or any other comparator we make.

Because arrayDeepCompare is curried, we can partially apply it like we did in the previous examples too

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

To me, this already a clear improvement over Tomáš's solution because I can explicitly choose a shallow or deep comparison for my arrays, as needed.


Object comparison (example)

Now what if you have an array of objects or something ? Maybe you want to consider those arrays as "equal" if each object has the same id value …

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

Simple as that. Here I've used vanilla JS objects, but this type of comparator could work for any object type; even your custom objects. Tomáš's solution would need to be completely reworked to support this kind of equality test

Deep array with objects? Not a problem. We built highly versatile, generic functions, so they'll work in a wide variety of use cases.

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

Arbitrary comparison (example)

Or what if you wanted to do some other kind of kind of completely arbitrary comparison ? Maybe I want to know if each x is greater than each y

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

Less is More

You can see we're actually doing more with less code. There's nothing complicated about arrayCompare itself and each of the custom comparators we've made have a very simple implementation.

With ease, we can define exactly how we wish for two arrays to be compared — shallow, deep, strict, loose, some object property, or some arbitrary computation, or any combination of these — all using one procedure, arrayCompare. Maybe even dream up a RegExp comparator ! I know how kids love those regexps …

Is it the fastest? Nope. But it probably doesn't need to be either. If speed is the only metric used to measure the quality of our code, a lot of really great code would get thrown away — That's why I'm calling this approach The Practical Way. Or maybe to be more fair, A Practical Way. This description is suitable for this answer because I'm not saying this answer is only practical in comparison to some other answer; it is objectively true. We've attained a high degree of practicality with very little code that's very easy to reason about. No other code can say we haven't earned this description.

Does that make it the "right" solution for you ? That's up for you to decide. And no one else can do that for you; only you know what your needs are. In almost all cases, I value straightforward, practical, and versatile code over clever and fast kind. What you value might differ, so pick what works for you.


Edit

My old answer was more focused on decomposing arrayEqual into tiny procedures. It's an interesting exercise, but not really the best (most practical) way to approach this problem. If you're interested, you can see this revision history.

如何在JavaScript中比较数组?

胡渣熟男 2025-02-17 19:54:22

如果您只有2个参数可提取,则wide_to_long将起作用。

在这里,您有3个,因此您可以使用多个索引进行手动重塑:

regex = r'alumn_(\d+)_subject_(\d+)_(.*)'

out = (df
 .set_index(['id', 'classroom', 'city'])
 .pipe(lambda d: d.set_axis(pd.MultiIndex
                              .from_frame(d.columns.str.extract(regex),
                                          names=['alumn', 'subject', None]
                                          ),
                            axis=1))
 .stack(['alumn', 'subject'])
 .reset_index()
)

输出:

Empty DataFrame
Columns: [id, classroom, city, alumn, subject, mark, name, teacher]
Index: []

输出单行(df.loc [0] = range = range(df.shape [1])):

     id  classroom  city alumn subject mark name teacher
0     0          1     2     0       0    3  203     403
1     0          1     2     0       1    4  204     404
2     0          1     2     0       2    5  205     405
3     0          1     2     0       3    6  206     406
4     0          1     2     0       4    7  207     407
..   ..        ...   ...   ...     ...  ...  ...     ...
195   0          1     2     9       5   98  298     498
196   0          1     2     9       6   99  299     499
197   0          1     2     9       7  100  300     500
198   0          1     2     9       8  101  301     501
199   0          1     2     9       9  102  302     502

[200 rows x 8 columns]

If you had only 2 parameters to extract, wide_to_long would work.

Here you have 3, thus you can perform a manual reshaping with a MultiIndex:

regex = r'alumn_(\d+)_subject_(\d+)_(.*)'

out = (df
 .set_index(['id', 'classroom', 'city'])
 .pipe(lambda d: d.set_axis(pd.MultiIndex
                              .from_frame(d.columns.str.extract(regex),
                                          names=['alumn', 'subject', None]
                                          ),
                            axis=1))
 .stack(['alumn', 'subject'])
 .reset_index()
)

output:

Empty DataFrame
Columns: [id, classroom, city, alumn, subject, mark, name, teacher]
Index: []

output with a single row (after df.loc[0] = range(df.shape[1])):

     id  classroom  city alumn subject mark name teacher
0     0          1     2     0       0    3  203     403
1     0          1     2     0       1    4  204     404
2     0          1     2     0       2    5  205     405
3     0          1     2     0       3    6  206     406
4     0          1     2     0       4    7  207     407
..   ..        ...   ...   ...     ...  ...  ...     ...
195   0          1     2     9       5   98  298     498
196   0          1     2     9       6   99  299     499
197   0          1     2     9       7  100  300     500
198   0          1     2     9       8  101  301     501
199   0          1     2     9       9  102  302     502

[200 rows x 8 columns]

熊猫重塑从colname提取多个值

更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文