cloudintheking

时光醉清风,总有人会记得


  • 首页

  • paint

  • works

  • 标签15

  • 分类6

  • 归档24

mongodb操作之$slice

发表于 2018-08-15 | 更新于 2021-04-26 | 分类于 翻译篇 | 评论数:
本文字数: 2.8k | 阅读时长 ≈ 3 分钟


翻译原文:https://docs.mongodb.com/manual/reference/operator/update/slice/#examples

$slice(切分)

当进行$push(插入)操作时,可以通过 $slice修饰词来限制插入的数组元素个数。如果想从一个只读操作中映射或是返回数组元素中特定的值,详见$slice映射操作。
$slice修饰词必须搭配$each修饰词才能使用。不过,你也可以传递一个空数组给$each修饰词,从而只让$slice修饰词起作用。

1
2
3
4
5
6
7
8
{
$push: {
<field>: {
$each: [ <value1>, <value2>, ... ],
$slice: <num>
}
}
}

< num > 的值可以是:

Value Description
0 更新数组<field>为空数组
负数 更新数组<field>只包含最后<num>个元素
正数 更新数组<field>只包含开头<num>个元素,适用于2.6以上版本

Behavior(行为)

这些修饰词出现的顺序是无关紧要的。不过在上一个版本中,要求$each修饰词得作为第一个修饰词出现,如果要和$slice修饰词连用的话。这里有一份关于和$push搭配使用的修饰词列表,详见Modifiers。
不结合$each修饰词而只使用$slice修饰词将会导致出错,不信可以试试。

栗子

从数组末尾切片

一个学生集合包含以下文档:

1
{ "_id" : 1, "scores" : [ 40, 50, 60 ] }

下面的操作增加一个新元素到scores数组中,然后使用$slice将数组修剪为最后五个元素。

1
2
3
4
5
6
7
8
9
10
11
db.students.update(
{ _id: 1 },
{
$push: {
scores: {
$each: [ 80, 78, 86 ],
$slice: -5
}
}
}
)

操作的结果就是将更新后的scores数组切分为最后5个元素

1
{ "_id" : 1, "scores" : [  50,  60,  80,  78,  86 ] }

从数组头部切片

一个学生集合包含以下文档:

1
{ "_id" : 2, "scores" : [ 89, 90 ] }

下面的操作增加一个新元素到scores数组中,然后使用$slice修饰词修剪为前三个元素。

1
2
3
4
5
6
7
8
9
10
11
db.students.update(
{ _id: 2 },
{
$push: {
scores: {
$each: [ 100, 20 ],
$slice: 3
}
}
}
)

操作的结果就是将更新后的scores数组切分为前三个元素中。

只用slice来更新数组

一个学生集合包含以下文档:

1
{ "_id" : 3, "scores" : [  89,  70,  100,  20 ] }

为了只用$slice修饰词来更新scores字段,我们得给出要切分的元素数量(比如 -3)赋给slice修饰词,而且赋一个空数组给$each修饰词,就像下面的代码:

1
2
3
4
5
6
7
8
9
10
11
db.students.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ ],
$slice: -3
}
}
}
)

操作的结果就是将scores数组切分为最后三个元素。

slice 和push搭配使用

一个学生集合包含以下文档:

1
2
3
4
5
6
7
8
9
{
"_id" : 5,
"quizzes" : [
{ "wk": 1, "score" : 10 },
{ "wk": 2, "score" : 8 },
{ "wk": 3, "score" : 5 },
{ "wk": 4, "score" : 6 }
]
}

下面的$push操作将会:

  • 使用$each修饰词来增加多个文档到quizzes数组中,
  • 使用$sort修饰词,按照score字段来降序排序修改过的quizzies数组中的全部元素,
  • 使用$slice修饰词,只保留quizzes数排中前三个排序过的元素。
1
2
3
4
5
6
7
8
9
10
11
12
db.students.update(
{ _id: 5 },
{
$push: {
quizzes: {
$each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],
$sort: { score: -1 },
$slice: 3
}
}
}
)

操作结果就是只保留了quizzes数组中分数最高的三个元素。

1
2
3
4
5
6
7
8
{
"_id" : 5,
"quizzes" : [
{ "wk" : 1, "score" : 10 },
{ "wk" : 2, "score" : 8 },
{ "wk" : 5, "score" : 8 }
]
}

上面操作中的修饰词都会被Mongodb自行处理,所有它们之间的书写顺序无关紧要。更多详情请见Modifiers。

oracle之表信息查询

发表于 2018-08-10 | 更新于 2021-04-26 | 分类于 数据库 | 评论数:
本文字数: 1.2k | 阅读时长 ≈ 1 分钟


个人笔记,如有描述不当,欢迎留言指出~

起因

主管抽风,想查询数据库’dbo‘中各表字段结构、外键信息、索引信息。于是任务交给了我…

语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
-- 各表字段结构
SELECT
TABLE_SCHEMA 数据库,
table_name 表名,
column_name 字段名,
data_type 类型,
is_nullable 是否为空,
column_default 默认值
FROM information_schema.columns
WHERE TABLE_SCHEMA = 'dbo'

-- 各表外键信息
SELECT
object_name(parent_object_id) 表名,
object_name(constraint_object_id) 约束名称,
col_name(parent_object_id, parent_column_id) 外键字段,
object_name(referenced_object_id) 关联表名,
col_name(referenced_object_id, referenced_column_id) 关联表字段
FROM sys.foreign_key_columns
WHERE referenced_object_id IN (
SELECT object_id(T.table_name)
FROM (
SELECT table_name
FROM information_schema.columns
WHERE TABLE_SCHEMA = 'dbo'
) T
)
ORDER BY object_name(parent_object_id)

-- 各表索引信息
SELECT
object_name(object_id) 表名,
name 索引名,
is_unique 是否唯一
FROM sys.indexes
WHERE Object_id IN (
SELECT object_id(T.table_name)
FROM (
SELECT table_name
FROM information_schema.columns
WHERE TABLE_SCHEMA = 'dbo'
) T
)
ORDER BY 表名

oracle之多表统计查询

发表于 2018-08-09 | 更新于 2021-04-26 | 分类于 数据库 | 评论数:
本文字数: 1.1k | 阅读时长 ≈ 1 分钟


起因

主管想根据时间范围统计下各标段各桥梁部件的录入数量,这个任务就交给我吧…

表介绍

  • qr_code_item_type:桥梁部件类型表,类型有桩基、承台、墩柱等
  • qr_code_item1 :桥梁墩柱类部件信息表,关联表qr_code_item_type、qr_code_main
  • qr_code_item2 :桥梁梁类部件信息表,关联表qr_code_item_type、qr_code_main
  • qr_code_main:桥梁标段表

    语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    SELECT itype.id,isnull(total, 0) total
    FROM qr_code_item_type itype
    LEFT JOIN (
    SELECT item.item_type_id type,COUNT(*) total
    FROM qr_code_item item
    LEFT JOIN qr_code_main main ON item.qr_code_main_id = main.id
    WHERE main.section = 2 AND isnull(item.update_time, item.create_time) BETWEEN '20180301' AND '20180801'
    GROUP BY item.item_type_id
    UNION ALL
    SELECT item.item_type_id type, COUNT(*) total
    FROM qr_code_item2 item
    LEFT JOIN qr_code_main main ON item.qr_code_main_id = main.id
    WHERE main.section = 2 AND isnull(item.update_time, item.create_time) BETWEEN '20180301' AND '20180801'
    GROUP BY item.item_type_id
    )
    aa ON itype.id = aa.type
    ORDER BY itype.id

ps:墩柱类、梁类虽都属于部件类,但具体信息差别较大,故分成两个表,所以统计的时候使用了联合查询

mongodb之主从、集群、分片

发表于 2018-08-07 | 更新于 2021-04-26 | 分类于 数据库 | 评论数:
本文字数: 2.3k | 阅读时长 ≈ 2 分钟


个人笔记,如有描述不当,欢迎留言指出~

核心语句

博客也好,官网也罢,密密麻麻一堆话,提炼浓缩就下面这几行命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#主从复制
mongod --port 27018 --dbpath "F:\mongodbSet\mongodb1\data" --logpath "F:\mongodbSet\mongodb1\log\mongodb.log" --logappend --master
mongod --port 27019 --dbpath "F:\mongodbSet\mongodb2\data" --logpath "F:\mongodbSet\mongodb2\log\mongodb.log" --logappend --slave --source=127.0.0.1:27018

#副本集
mongod --port 27018 --dbpath "F:\mongodbSet\mongodb1\data" --logpath "F:\mongodbSet\mongodb1\log\mongodb.log" --logappend --replSet myrs
mongod --port 27019 --dbpath "F:\mongodbSet\mongodb2\data" --logpath "F:\mongodbSet\mongodb2\log\mongodb.log" --logappend --replSet myrs
mongod --port 27020 --dbpath "F:\mongodbSet\mongodb3\data" --logpath "F:\mongodbSet\mongodb3\log\mongodb.log" --logappend --replSet myrs

#分片+副本集
#config
mongod --port 27018 --bind_ip 127.0.0.1 --configsvr --dbpath "F:\mongodbSet\config\mongodb1\data" --logpath "F:\mongodbSet\config\mongodb1\log\mongodb.log" --logappend --replSet configs
mongod --port 27019 --bind_ip 127.0.0.1 --configsvr --dbpath "F:\mongodbSet\config\mongodb2\data" --logpath "F:\mongodbSet\config\mongodb2\log\mongodb.log" --logappend --replSet configs
mongod --port 27020 --bind_ip 127.0.0.1 --configsvr --dbpath "F:\mongodbSet\config\mongodb3\data" --logpath "F:\mongodbSet\config\mongodb3\log\mongodb.log" --logappend --replSet configs

#shard
mongod --port 27024 --bind_ip 127.0.0.1 --shardsvr --dbpath "F:\mongodbSet\shared\mongodb1\data" --logpath "F:\mongodbSet\shared\mongodb1\log\mongodb.log" --logappend --replSet shard
mongod --port 27025 --bind_ip 127.0.0.1 --shardsvr --dbpath "F:\mongodbSet\shared\mongodb2\data" --logpath "F:\mongodbSet\shared\mongodb2\log\mongodb.log" --logappend --replSet shard
mongod --port 27026 --bind_ip 127.0.0.1 --shardsvr --dbpath "F:\mongodbSet\shared\mongodb3\data" --logpath "F:\mongodbSet\shared\mongodb3\log\mongodb.log" --logappend --replSet shard

#mongos
mongos --port 27021 --configdb configs/127.0.0.1:27018,127.0.0.1:27019,127.0.0.1:27020 --replSet mongos

相关命令解释

  • –port <端口号>: 设置mongo服务开启的端口
  • –dbpath <数据存储路径>:设置mongo数据存储路径
  • –logpath <日志存储路径>:设置mongo日志存储路径
  • –logappend :启用日志追加方式,否则新日志会覆盖旧日志
  • –master :设置为master方
  • –slave:设置为slave方
  • –source = < ip : port>:设置master服务的地址
  • –replSet <集群名>:设置集群名称

我的装备清单

发表于 2018-08-06 | 更新于 2021-04-26 | 分类于 环境安装篇 | 评论数:
本文字数: 513 | 阅读时长 ≈ 1 分钟


个人笔记,如有描述不当,欢迎留言指出~

why?

随着技术栈的加深,认识的语言和工具也越来越多,若是整理出一份清单,重装环境的时候想想头就大...

开发环境

  • Maven
  • DosBox
  • Git
  • Python
  • Node.js
  • Java
  • nginx
  • nvm
  • masm32

开发工具

  • IDE
    • IntelliJ IDEA
    • PyCharm
    • WebStorm
    • Visual C++6.0 密码:ec13
  • 反编译神器
    • Bytecode Viewer
  • 数据可视化工具
    • DataGrip
    • Redis Desktop Manager
    • NoSQL Manager
  • 虚拟机
    • vmware 密码:t8i3
  • 容器
    • Docker
  • git管理工具
    • 小乌龟
  • 终端连接工具
    • xshell
  • 远程桌面工具
    • TeamViewer
  • 下载神器
    • IDM
  • 转码神器
    • FFmpeg
  • 科学上网
    • shadowsocksR 密码:0w5g
  • 其他
    • 印象笔记
    • 马克飞象
    • 微信
    • Chrome(需翻墙)
    • 火绒(比360良心100倍)
    • 百度网盘
    • 7-zip
    • Postman(restfulsapi 调试神器 )

Flex-Layout之声明式API概述

发表于 2018-08-04 | 更新于 2021-04-26 | 分类于 翻译篇 | 评论数:
本文字数: 1.9k | 阅读时长 ≈ 2 分钟


翻译原文:https://github.com/angular/flex-layout/wiki/Declarative-API-Overview

静态API概述

Flex layout 的特点就是提供敏捷的语法性的指令允许开发者利用弹性盒子CSS样式来轻松直观地创建响应且自适应的布局。

这个API概述可以被视作静态的,提供一个随浏览器宽度改变而调整元素的大小和位置的用户体验。这个静态API可以被视为默认桌面布局API。
开发者应该使用响应式API来支持手机或平板设备的交互式布局配置。

Flex-Layout 是一组直观的HTML指令(aka属性)列表,可以被用于HTML容器和元素。开发者可以直接在HTML中定义他们自己的布局声明。
一个重要的基本的概念就是理解哪些API被用在DOM容器上,哪些被用在DOM容器的子元素上。

用于DOM容器的API:

HTML API Allowed values
fxLayout < direction > [wrap] row / column / row-reverse / column-reverase
fxLayoutAlign < main-axis > < cross-axis> main-axis: start / center / end / space-around / space-between; cross-axis: start / center / end / stretch
fxLayoutGap % / px / vw / vh

这些指令会影响容器中子元素的流向和布局。

用于DOM元素的API:

HTML Allowed values
fxFlex “” / px / % / vw / vh < grow> < shrink> < basis>
fxFlexOrder int
fxFlexOffset % / px / vw / vh
fxFlexAligin start / baseline / center / end
fxFlexFill,fxFill

这些指令影响宿主元素的布局和大小。注意这些API期望它们的宿主元素内置于一个弹性盒子的DOM容器里(一个块元素,它本身使用布局API来作为容器)。

用于任意元素的API :

HTML API Allowed values
fxHide TRUE / FALSE / 0 / “”
fxShow TRUE / FALSE / 0 / “”
ngClass @extends ngClass core
ngStyle @extends ngStyle core
imgSrc @extends src attribute

下面展示的是使用容器和元素的静态API来写的一个简单的HTML标记:

1
2
3
4
5
6
7
8
9
<div fxLayout='column' class="zero">
<div fxFlex="33" class="one" ></div>
<div fxFlex="33%" [fxLayout]="direction" class="two">
<div fxFlex="22%" class="two_one"></div>
<div fxFlex="205px" class="two_two"></div>
<div fxFlex="30" class="two_three"></div>
</div>
<div fxFlex class="three"></div>
</div>

Flex Layout指令直接分配CSS样式内嵌到宿主元素中,这些内嵌样式会覆盖掉继承的样式、影子DOM样式,甚至是所有基于:host元素的影子DOM树形样式。

响应式API

Flex-Layout 也拥有一套巨大的响应特征来确保开发者能够轻松地改变不同显示设备之间的用户体验布局配置。更多文档资料请至 Responsive API page。

本文仅作翻译,关于弹性布局框架的相关知识,推荐博文。
后期我会抽空翻译Flex-Layout的其他文章。

Nginx之正反向代理

发表于 2018-08-02 | 更新于 2021-04-26 | 分类于 后端笔记 | 评论数:
本文字数: 1.7k | 阅读时长 ≈ 2 分钟


个人笔记,如有描述不当,欢迎留言指出~

前言

科学上网过的小伙伴们都知道,目前这些上网工具SS、SSR、V2Ray等等,说白了就是通过代理让我们得以愉快地遨游在知识的海洋里。

正向代理

概念

正向代理是什么?由于某些网站访问奇慢,或者墙的问题根本无法访问时,通过给浏览器配置代理ip和端口,让代理服务器转发我们请求,而后将响应结果传回浏览器,这就是正向代理。举个通俗的栗子,就好比你自己没找到合适的房子,于是你通过房租中介来租到好房子。大致流程如下:
Alt text

nginx正向代理主要配置

服务端

在虚拟机上部署了一台nginx服务器(有独立局域网ip)

1
2
3
4
5
6
7
8
server {  
resolver 114.114.114.114 8.8.8.8; #指定DNS服务器IP地址
listen 8888; #监听端口
location / {
proxy_pass $scheme://$host$request_uri; #设定代理服务器的协议和地址
proxy_set_header Host $http_host;
}
}

然后重启nginx生效

客户端

打开Chrome浏览器->设置->高级->系统->打开代理设置,如图所示:
Alt text

其中,192.168.1.44就是你新建虚拟机的独立局域网IP。

反向代理

概念

你可以这么理解,正向代理服务器只是转发代理请求,并不提供自己的服务;而反向代理可以提供自己的服务。比如说,有个请求想要访问你公司内网服务器,而实际公司只有一个公共IP,内网IP并没有映射,所以这时候你就可以使用nginx反向代理来实现内网资源的请求。另外,如果访问量过大,还可以使用nginx来进行负载均衡。大致流程如下:
Alt text

nginx反向代理主要配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
upstream  clusterserver {  
#不设置,则默认是轮询
#least_conn; #最少连接数
#ip_hash; #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
server 192.1.168.45:9991 weight=1; #weight值为1~10,代表权重,和访问比率成正比,用于后端服务器性能不均的情况
server 192.1.168.46:9991 weight=1;
#server 192.1.168.45:9993 weight=1 down; #手工设置该服务不可用
#server 192.1.168.45:9994 weight=1 backup; #其他主服务器都挂了,自动开启这个备用服务。
}

server {
listen 9999;
server_name xxx; #你的域名或者公共IP
location / {
root html;
index index.html index.htm;
proxy_pass http://clusterserver;
proxy_connect_timeout 1; #单位为秒 超时设置,如果超时将请求其他服务
#proxy_send_timeout 1;
#proxy_read_timeout 1;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

这样当代理服务器监听到9999端口的请求时,根据proxy_pass配置找到名为clusterserver的upstream 节点来进行负载均衡。

powershell之启动远程jar服务

发表于 2018-07-29 | 更新于 2021-04-26 | 分类于 后端笔记 | 评论数:
本文字数: 2.6k | 阅读时长 ≈ 2 分钟


个人笔记,如有描述不当,欢迎留言指出~

起因

主管抽风说每次都要登录远程服务器再启动jar太麻烦了,要是有个一键启动远程jar的批处理就是。于是这个任务就交给我了…

powershell配置

用管理员权限启动 PowerShell,执行下面的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#客户端或服务器公共配置:
Get-Service WinRM #查看WinRM服务的状态
Enable-PSRemoting –Force #配置系统接受远程命令
Set-Service WinRM -StartMode Automatic #开启WinRM服务自启动
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="3000"}' #设置powershell最大内存 方法一推荐
Set-Item WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB 3000 #设置最大内存 方法二
Restart-Service winrm //重启winrm服务使配置生效


#服务器配置:
Set-Item WSMan:localhost\client\trustedhosts -value "192.168.1.44,192.168.1.45" #设置设置主机可信任的客户端地址
winrm set winrm/config/client @{TrustedHosts="192.168.1.45,192.168.1.44"} #设置设置主机可信任的客户端地址,当上个命令无效时,可选用该命令(该命令请在cmd中使用)
Get-Item WSMan:\localhost\Client\TrustedHosts #查看可信任主机
get-executionpolicy #查看脚本执行策略
set-executionpolicy remotesigned #设置执行策略为远程可执行
Restart-Service winrm #重启服务生效

Test-WsMan xxx.xxx.xxx.xxx #客户端测试远程连接

jar包上传处理命令

服务器上必须安装了ftp,否则没法上传文件。我公司服务器系统是windows server 2008,用它自带的IIS创建ftp,并设置虚拟目录。

新建上传文件脚本up.bat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
curl -X POST 192.168.1.44:8886/shutdown #关闭44服务器上8886端口服务
curl -X POST 192.168.1.44:8887/shutdown#关闭44服务器上8887端口服务
curl -X POST 192.168.1.44:8888/shutdown#关闭44服务器上8888端口服务

Echo open 192.168.1.44 >ftp.up #打开连接44服务器ftp连接
Echo Administrator>>ftp.up #服务器上登录用户名
Echo 59@SDS25>>ftp.up #登录密码
Echo cd .\project1>>ftp.up #因为进入的是ftp的根目录,所以使用.\project1,进入根目录下的project1
Echo binary>>ftp.up #二进制数据传输格式
Echo put "E:\Workspace\idea\jcnyJava\target\jcny-java-0.0.1-SNAPSHOT.jar">>ftp.up #传送本地文件到ftp中
Echo cd ..\project2>>ftp.up #使用..\project2,进入根目录下的project2目录
Echo put "E:\Workspace\idea\jcnyJava\target\jcny-java-0.0.1-SNAPSHOT.jar.original">>ftp.up #传送本地文件到ftp中
Echo cd ..\project3>>ftp.up #进入根目录下的project3目录
Echo put "E:\Workspace\idea\jcnyJava\target\jcny-java-0.0.1-SNAPSHOT.jar.original">>ftp.up #传送本地文件到ftp中
Echo bye>>ftp.up #客户端关闭ftp连接
FTP -s:ftp.up #服务器关闭ftp连接
del ftp.up /q #删除ftp连接
Pause

powershell启动远程服务命令

新建一个启动脚本deploy.ps1

1
2
3
4
5
6
7
8
$na = "yourname"  #服务器用户名

$p2 = ConvertTo-SecureString "yourpassword" -AsPlainText -Force #加密登录密码
$A = New-Object System.Management.Automation.PSCredential($na,$p2) #创建连接
Invoke-Command -ComputerName 192.168.1.44 -Credential $A -ScriptBlock { #执行远程操作
Set-Location E:\webroot\projects #进入远程服务器目录
invoke-expression -command E:\webroot\tongtu-projects\startall.bat #远程服务启动的脚本路径
}

以上命令都是针对Windows系统的,Linux系统应该是写bash脚本吧。
如果下次主管说要一键启动远程Linux上的服务的话,到时候我再写篇linux的吧。

Python虚拟环境搭建

发表于 2018-07-26 | 更新于 2021-04-26 | 分类于 环境安装篇 | 评论数:
本文字数: 1.3k | 阅读时长 ≈ 1 分钟


个人笔记,如有描述不当,欢迎留言指出~

应用场景

搭建 Python 虚拟环境,可以方便地Python2,Python3 共存。避免包的混乱和版本的冲突。为每个应用程序单独创建虚拟环境可以保证程序中能访问虚拟环境中的包,保持解释器环境的干净整洁。virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。

我的开发环境

  • windows 10
  • python2.7
  • python3.5

安装使用 virtualenv

前言

因为我装了python2.7、3.5,所以也就有了两个pip包管理工具,默认会使用高版本python的pip,but也可以指定s使用哪个Python版本的pip,如pip2指定使用Python2.7的pip。

安装

1
pip3 install virtualenv

创建虚拟环境

1
2
cd your_project_dir #进入你的工程目录
virtualenv env1 -p G:\Environment\Python\Python27 --no-site-packages
  • env1:虚拟环境目录名
  • -p:指定Python安装路径
  • –no-site-packages: 不复制系统Python环境中的所有第三方包

这样我们就得到了一个不带任何第三方包的“干净”的Python2.7运行环境。

激活虚拟环境

cd env1 #进入虚拟环境
cd Scirpts #进入脚本目录
activate #激活虚拟环境
deactivate #退出虚拟环境

截图如下:
Alt text

当执行activate时,注意命令提示符变了,有个(env1)前缀,表示当前环境是一个名为env1的Python环境。

虽然virtualenv很强大,但仍有不足。你想,要是以后创建的虚拟环境多了,它们分散在系统各处,时间一长,你可能忘记它们的名字或者位置。所以下面介绍virtualenvwrapper。

安装使用 virtualenvwrapper

介绍

virtualenvwrapper 是对 virtualenv 的功能扩展,可以管理全部的虚拟环境,用单个命令方便切换不同的虚拟环境。

安装

pip install virtualenvwrapper-win 

设置workon_home环境变量

Alt text

基本命令

新建虚拟环境

如果不指定Python解释器程序路径,则会默认使用系统里高版本Python

1
mkvirtualenv env2

mkvirtualenv –python=(pytho执行路径) (虚拟环境名字)

1
mkvirtualenv --python=G:\Environment\Python\Python27\python.exe mypython27

查看安装的所有虚拟环境

workon

Alt text

进入和退出虚拟环境

1
2
workon mypython27
deactivate

Alt text

其他

1
mkvirtualenv -h #更多命令大家自己探索吧

后记

创建python虚拟环境的技术不只有virtualenv,现在最新的是pyenv技术,这也是官方推荐使用的,后期有时间再专门写篇吧
另外 pycham这个IDE自带了Python虚拟环境创建功能,jetbrains系列就是Alt text

二叉查找树之C++实现

发表于 2018-07-20 | 更新于 2021-04-26 | 分类于 算法篇 | 评论数:
本文字数: 8.2k | 阅读时长 ≈ 7 分钟


个人笔记,如有描述不当,欢迎留言指出~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

template<class T>
struct BSTreeNode{
T key;
BSTreeNode *left;
BSTreeNode *right;
BSTreeNode *parent;
BSTreeNode(T k ){
key=k;
left=NULL;
right=NULL;
parent=NULL;
}
BSTreeNode(){};
};
//错误信息
struct ErrorMessage{
bool flag;
string message;
};

//生成节点并插入树中
template<class T>
ErrorMessage insert(BSTreeNode<T>* &root,T key){
BSTreeNode<T>* node=NULL;
ErrorMessage error;
stringstream s;
if ((node=new BSTreeNode<T>(key)) == NULL)
{
s<<"值"<<key<<"分配节点内存失败";
error.flag=false;
error.message= s.str();
return error;
}
BSTreeNode<T>* x= root;
BSTreeNode<T>* y= NULL;
while (x !=NULL)
{
y=x;
if (node->key<x->key)
{
x=x->left;
}
else if(node->key>x->key){
x=x->right;
}
else{
s<<"值"<<key<<"重复,创建节点失败";
error.flag=false;
error.message=s.str();
return error;
}
}
node->parent=y;
if (y==NULL)
{
root = node;
}
else if(node->key<y->key){
y->left=node;
}
else{
y->right=node;
}
s<<"值"<<key<<"创建节点成功";
error.flag=true;
error.message=s.str();
return error;
}
//前序遍历
template<class T >
void preShow(BSTreeNode<T>* node){
if (node != NULL)
{
cout<<node->key<<" ";
preShow(node->left);
preShow(node->right);
}
}
//中序遍历
template<class T>
void midShow(BSTreeNode<T>* node){
if (node !=NULL)
{
midShow(node->left);
cout<<node->key<<" ";
midShow(node->right);
}
}

//后序遍历
template<class T >
void postShow(BSTreeNode<T>* node){
if (node != NULL)
{
cout<<node->key<<" ";
postShow(node->left);
postShow(node->right);
}
}

// 查找节点树下包含key的节点
template<class T >
BSTreeNode<T>* search(BSTreeNode<T>* node,T key){
if (node == NULL || node->key == key)
{
return node;
}
else
{
if (node->key>key)
{
search(node->left,key);
}
else if (node->key<key)
{
search(node->right,key);
}
}
}
// 返回节点树中最大值的节点
template<class T >
BSTreeNode<T>* maxNode(BSTreeNode<T>* node){
if (node==NULL)
{
return NULL;
}
if (node->right==NULL)
{
return node;
}
else
{
maxNode(node->right);
}
}

// 返回节点树中最小值的节点
template<class T >
BSTreeNode<T>* minNode(BSTreeNode<T>* node){
if (node==NULL)
{
return NULL;
}
if (node->left==NULL)
{
return node;
}
else
{
minNode(node->left);
}
}
//返回传入节点的后继节点
template<class T>
BSTreeNode<T>* successor(BSTreeNode<T>* node){
if(node == NULL){
return NULL;
}
if (node->right!=NULL)
{
return minNode(node->right);
}
BSTreeNode<T>* parent=node->parent;
BSTreeNode<T>* child=node;
while(parent!=NULL&&parent->left!=child){
child=parent;
parent=parent->parent;
}
return parent;
}

// 返回传入节点的前驱节点
template<class T>
BSTreeNode<T>* predecessor(BSTreeNode<T>* node){
if (node == NULL)
{
return NULL;
}
if (node->left!=NULL)
{
return maxNode(node->left);
}
BSTreeNode<T>* parent=node->parent;
BSTreeNode<T>* child=node;
while(parent!=NULL&&parent->right!=child){
child=parent;
parent=parent->parent;
}
return parent;
}
//删除节点
template<class T>
void delete_node(BSTreeNode<T>* &root, BSTreeNode<T>* node){
if (node->left==NULL&&node->right==NULL) //叶子节点
{
if (node == root)
{
root=NULL;
}
else if (isLeft(node))
{
node->parent->left=NULL;
}
else{
node->parent->right=NULL;
}
}
else if (node->left==NULL) //只有右子节点
{
if (node == root) //节点是根节点
{
root=node->right;
node->right->parent=NULL;
}
else if (isLeft(node)) //节点是左节点
{
node->parent->left=node->right;
node->right->parent=node->parent;
}
else{ //节点是右节点
node->parent->right=node->right;
node->right->parent=node->parent;
}
}
else if (node->right==NULL) //只有左节点
{
if (node == root) //节点是根节点
{
root=node->left;
node->left->parent=NULL;
}
else if (isLeft(node)) //节点是左节点
{
node->parent->left=node->left;
node->left->parent=node->parent;
}
else{ //节点是右节点
node->parent->right=node->left;
node->left->parent=node->parent;
}
}
else //左右节点都有
{
BSTreeNode<T>* suc= successor(node); //node 的后继节点
if (suc == node->right) //后继节点为右子节点
{
if (node == root)// 删除节点为根节点
{
root=suc;
suc->left=node->left;
node->left->parent=suc;
}
else{// 删除节点不为根节点
if (isLeft(node)) //删除节点为左节点
{
node->parent->left= suc;
}
else{ // 删除节点为右节点
node->parent->right=suc;
}
suc->parent=node->parent;
suc->left=node->left;
node->left->parent=suc;
}
}
else //后继节点不为右子节点
{
suc->parent->left=suc->right;
if (suc->right!=NULL) // 后继节点的右节点不空
{
suc->right->parent= suc->parent;
}
suc->left =node->left;
node->left->parent =suc;
suc->right=node->right;
node->right->parent =suc;
suc->parent=node->parent;
if (node==root)
{
root=suc;
}
}
}
delete node;
node=NULL;
}
template<class T>
bool deleteByKey(BSTreeNode<T>* &root, T key){
BSTreeNode<T>* node= search(root,key);
if (node == NULL)
{
return false;
}
else{
delete_node(root,node);
return true;
}
}
// 判断是否为左节点
template<class T>
bool isLeft(BSTreeNode<T>* node){
if (node->parent!=NULL&&node->parent->left==node)
{
return true;
}
return false;
}
int main(){

BSTreeNode<int>* root=NULL;
cout<<insert(root,5).message<<endl;
cout<<insert(root,3).message<<endl;
cout<<insert(root,1).message<<endl;
cout<<insert(root,2).message<<endl;
cout<<"前序"<<endl;
preShow(root);
cout<<endl<<"中序"<<endl;
midShow(root);
cout<<endl<<"后序"<<endl;
postShow(root);
cout<<endl;
if (search(root,4) != NULL)
{
cout<<"存在"<<4<<endl;
}else{
cout<<"不存在"<<4<<endl;
}
cout<<"最大值:"<<maxNode(root)->key<<endl;
cout<<"最小值:"<<minNode(root)->key<<endl;
cout<<"3的后继:"<<successor(search(root,3))->key<<endl;
cout<<"3的前驱:"<<predecessor(search(root,3))->key<<endl;
if ( deleteByKey(root,5))
{
cout<<"5删除成功"<<endl;
}
else
{
cout<<"5删除成功"<<endl;
}
cout<<"中序"<<endl;
midShow(root);

return 0;
}

123
cloudintheking

cloudintheking

北落师门

24 日志
6 分类
15 标签
RSS
GitHub segmentfault E-Mail   High
Links
  • V2EX
  • 掘金
© 2018 — 2022 cloudintheking | 站点总字数: 102k | 站点阅读时长 ≈ 1:32