UniRx之操作符详解-Linq语法

news2024/9/22 11:32:17

前言

UniRx中由很多操作符,注意要分为三类

  • Linq操作符,和Linq语法风格一致
  • Rx操作符,从Rx.Net库继承下来的操作符。
  • UniRx操作符,UniRx针对Unity的独有操作符。

Rx和Linq

Linq是微软的一项技术,新增一种自然查询的SQL语法到.NetFramework的编程语言中。
Rx最初是微软Linq的一个扩展库,让开发者可以利用可观察序列和Linq风格查询操作符编写异步和基于事件的程序。2012年被开源了。目标是提供一致性的编程接口,帮助开发者方便的处理异步数据流。Rx支持.Net,JS,Java,C++等,近几年越来越流行,已经支持几乎全部的流行编程语言。Rx目前大部分语言库是由Rx组织负责维护。Rx的Unity版本就是UniRx。
Rx.io 官方给的定义是:Rx 是一个使⽤可观察数据流进行异步编程的编程接⼝。
我们可以这么来理解:Rx=Observables+Linq+Schedulers,Rx结合了观察者模式,迭代器模式和函数式编程的精华。
Rx的编程风格几乎是和Linq一致的,所以我们从Linq操作符来学习Rx是最合适不过的了。

操作符

where

LINQ 中的 Where 操作符与 SQL 命令中的 Where 作用相似,都是起到范围限定也就是过滤作用的,而
条判断条件就是它后面所接的子句

  • LINQ Where
// 查询⼤大于 45 岁的学⽣生:
var students = new List<Student>()
{
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "李李四", Age = 40}
};
var oldStudents = students.Where(student => student.Age > 45);
foreach (var student in oldStudents)
{
	Debug.Log(student.Name);
}

输出结果
// 结果
// 张三
// 张三
  • UniRx Where
    在这里插入图片描述
Observable.EveryUpdate()
.Where(_ => Input.GetMouseButtonDown(0))
.Subscribe(_ => { Debug.Log("mouse down"); })
.AddTo(this);

鼠标左键点击打印mouse down

Select

LINQ 中的 Select 操作符 与 SQL 命令中的 Select 作用相似,但是位置不同,查询表达式中的 select 及
所接子句是放在最后并把子句中的变量也就是结果返回来

  • LINQ Select
var students = new List<Student>()
{
new Student() {Name = "张三", Age = 50},
new Student() {Name = "张三", Age = 50},
new Student() {Name = "李李四", Age = 40}
};
var oldStudentNames = students.Where(student => student.Age > 45)
.Select(student => student.Name);
foreach (var studentName in oldStudentNames)
{
  Debug.Log(studentName);
}

输出结果为:
张三
张三
  • UniRx Select
    在这里插入图片描述
Observable.EveryUpdate()
.Where(_ => Input.GetMouseButtonUp(0))
.Select(_ => "mouse up")
.Subscribe(Debug.Log)
.AddTo(this);

当每次抬起⿏鼠标左键,则输出 mouse up。

First

取序列中的第一个元素。First 有两种形式,一种是直接获取第一个元素,第二种则是取序列中满足条件
的第一个元素

  • LINQ First
var students = new List<Student>()
{
new Student() {Name = "张三", Age = 50},
new Student() {Name = "张三", Age = 50},
new Student() {Name = "李李四", Age = 40}
};
var oldStudent = students
.Where(student => student.Age > 45)
.First();
Debug.Log(oldStudent.Name);
 
输出结果为: 张三
  • UniRx First
    在这里插入图片描述
Observable.EveryUpdate()
.First(_ => Input.GetMouseButtonDown(0))
.Subscribe(_ => { Debug.Log("mouse down"); })
.AddTo(this);

当⿏标点击按下的时候,输出 mouse down。

Distinct

筛选序列中不相同的值。⽤用于查询不重复的结果集。生成 SQL 语句为: SELECT DISTINCT [City] FROM
[Customers]

  • LINQ Distinct
var names = new List<string>()
{
	"张三",
	"张三",
	"李李四",
};
var distinctNames = names.Distinct();
foreach (var distinctName in distinctNames)
{
	Debug.Log(distinctName);
}

输出结果为:
张三
李李四
  • UniRx Distinct
    在这里插入图片描述
var students = new List<Student>()
{
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "李李四", Age = 40}
};
students.ToObservable()
.Distinct(student=>student.Name)
.Subscribe(student =>
{
	Debug.Log(student.Name);
});


var leftClickStream = Observable.EveryUpdate()
	.Where(_ => Input.GetMouseButtonDown(0))
	.Select(_ => "left clicked");
var rightClickStream = Observable.EveryUpdate()
	.Where(_ => Input.GetMouseButtonDown(1))
	.Select(_ => "right clicked");
Observable.Merge(leftClickStream,rightClickStream)
	.Distinct()
	.Subscribe(Debug.Log)
	.AddTo(this);

不管点击多少次鼠标左键,还是鼠标右键,输出只输出一次 “left clicked” 和 “right
clicked”

Last

取序列列中的最后⼀一个元素

  • LINQ Last
var students = new List<Student>()
{
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "李四", Age = 40}
};
var lastStudent = students.Last();
Debug.Log(lastStudent.Name);

输出结果为
李四
  • UniRx Last
    在这里插入图片描述
new List<Student>()
{
new Student() {Name = "张三", Age = 50},
new Student() {Name = "张三", Age = 45},
new Student() {Name = "李四", Age = 50}
}
.ToObservable()
.Last(student => student.Age == 50)
.Subscribe(student => { Debug.Log(student.Name); });

输出结果为:
李四

SelectMany

将序列的每个元素投影到 IEnumerable 并将结果序列合并为一个序列。对每项再进行行遍历处理再进行行合成序列

  • LINQ SelectMany
var students = new List<Student>()
{
	new Student() {Name = "张三", Age = 50},
	new Student() {Name = "张三", Age = 45},
	new Student() {Name = "李四", Age = 50}
}
var singleChars = students.SelectMany(student => student.Name + ":" +
student.Age);
foreach (var singleChar in singleChars)
{
	Debug.Log(singleChar);
}

输出结果为: 张三 : 50 张三 : 45 李四 : 50
  • UniRx SelectMany
    在这里插入图片描述
IEnumerator A()
{
	yield return new WaitForSeconds(1.0f);
	Debug.Log("A");
}
IEnumerator B()
{
	yield return new WaitForSeconds(2.0f);
	Debug.Log("B");
}
IEnumerator C()
{
	yield return new WaitForSeconds(3.0f);
	Debug.Log("C");
}
 
var streamA = Observable.FromCoroutine(A);
var streamB = Observable.FromCoroutine(B);
var streamC = Observable.FromCoroutine(C);
streamA.SelectMany(streamB.SelectMany(streamC))
.Subscribe(_ => Debug.Log("Hello"));

输出结果为:
A
B
C
Hello

Take

从序列列的开头返回指定数量量的相邻元素。

  • LINQ Take
int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
var topThreeGrades = grades.OrderByDescending(grade => grade) // 根据分数降序排序
.Take(3);
Debug.Log("分数前三名的是:");
foreach (var topThreeGrade in topThreeGrades)
{
Debug.Log(topThreeGrade);
} 

输出结果为:
分数前三名的是:
98
92
85
  • UniRx Take
    在这里插入图片描述
this.UpdateAsObservable()
.Where(_=>Input.GetMouseButtonDown(0))
.Take(5)
.Subscribe(_ => Debug.Log(1));


输出结果为,只有前 5 次⿏鼠标点击才会输出 1

Concat

连接两个序列列。

  • LINQ Concat
Pet[] cats =
{
	new Pet {Name = "Barley", Age = 8},
	new Pet {Name = "Boots", Age = 4},
	new Pet {Name = "Whiskers", Age = 1}
};
Pet[] dogs =
{
	new Pet {Name = "Bounder", Age = 3},
	new Pet {Name = "Snoopy", Age = 14},
	new Pet {Name = "Fido", Age = 9}
};
var petNames = cats.Select(cat => cat.Name).Concat(dogs.Select(dog => dog.Name));
foreach (var petName in petNames)
{
	Debug.Log(petName);
}

输出结果:
Barley
Boots
Whiskers
Bounder
Snoopy
Fido
  • UniRx Concat
    在这里插入图片描述
var a = this.UpdateAsObservable().Take(3).Select(_ => "A");
var b = this.UpdateAsObservable().Take(2).Select(_ => "B");
var c = a.Concat(b);
c.Subscribe(Debug.Log);

输出结果:
A
A
A
B
B

WhenAll

确定序列列中的所有元素是否都满⾜足条件。

  • LINQ All
Pet[] pets =
{
	new Pet {Name = "Barley", Age = 10},
	new Pet {Name = "Boots", Age = 4},
	new Pet {Name = "Whiskers", Age = 6}
};
var allStartWithB = pets.All(pet =>
pet.Name.StartsWith("B"));
Debug.LogFormat("{0} pet names start with 'B'.",allStartWithB ? "All" : "Not all");


输出结果为:
Not all pet names start with 'B'.
  • UniRx WhenAll
var streamA = Observable.FromCoroutine(A);
var streamB = Observable.FromCoroutine(B);
var streamC = Observable.FromCoroutine(C);
 
Observable.WhenAll(streamA, streamB, streamC)
.Subscribe(_ => { Debug.Log("Completed"); });

输出结果为(A、B、C 输出顺序不不⼀一定):
B
C
A
Completed

OfType

OfType根据指定类型筛选 IEnumerable 的元素。

  • LINQ OfType
var list = new ArrayList {30, 30.0f, "test"};
var filterList = list.OfType<float>();
foreach (var obj in filterList)
{
	Debug.Log(obj);
}

输出结果为:
30
  • UniRx OfType
    在这里插入图片描述
// 创建一个 Subject(Observable)
var objects = new Subject<object>();
 
// 订阅该 Observable,进行行类型过滤
objects.OfType<object, string>()
.Subscribe(Debug.Log);
// 手动发送数据
objects.OnNext(1);
objects.OnNext(2);
objects.OnNext("3");
objects.OnNext(4);
// 手动结束
objects.OnCompleted();

输出结果为:
3

Cast

将 IEnumerable 的元素强制转换为指定的类型

  • LINQ Cast
var fruits = new ArrayList {"mango", "apple", "lemon"};
var fruitNames = fruits.Cast<string>();
// 等同于
// var fruitNames = fruits.Select(fruit => fruit.ToString);
foreach (var fruit in fruitNames)
{
	Debug.Log(fruit);
}

输出代码为:
mango
apple
lemon
  • UniRx Cast
    在这里插入图片描述
// 创建⼀一个 Subject(Observable)
var objects = new Subject<object>();
// 订阅该 Observable,进⾏行行类型转换
objects.Cast<object,int>().Subscribe(i => Debug.Log(i));
// ⼿手动发送数据
objects.OnNext("1");
objects.OnNext("2");
objects.OnNext(3);
// ⼿手动结束
objects.OnCompleted();

输出结果为:
1
2
3

GroupBy

对序列列中的元素进⾏行行分组

  • LINQ GroupBy
var students = new List<Student>()
{
	new Student {Name = "张三", Age = 50},
	new Student {Name = "张三", Age = 50},
	new Student {Name = "李四", Age = 40}
};
var studentGroup4Names = students.GroupBy(student => student.Name);
foreach (var studentGroup in studentGroup4Names)
{
	Debug.LogFormat("Group Key:{0}", studentGroup.Key);
	foreach (var student in studentGroup)
	{
		Debug.LogFormat("Name:{0} Age:{1}", student.Name, student.Age);
	}
}

输出结果为:
Group Key:张三
Name:张三 Age:50
Name:张三 Age:50
Group Key:李四
Name:李四 Age:40
  • UniRx GroupBy
    在这里插入图片描述
Observable.Interval(TimeSpan.FromSeconds(0.1))
.Take(10)
.GroupBy(i => i % 3)
.Subscribe(group =>
{
	group.Subscribe(number => { 
		Debug.LogFormat("Key:{0},Number:{1}",group.Key, number); 
	});
});

输出结果为:
Key:0,Number:0
Key:1,Number:1
Key:2,Number:2
Key:0,Number:3
Key:1,Number:4
Key:2,Number:5
Key:0,Number:6
Key:1,Number:7
Key:2,Number:8
Key:0,Number:9

Range

生成指定范围内的整数的序列

  • LINQ Range
var squares = Enumerable.Range(5, 3).Select(x => x * x);
foreach (var square in squares)
{
	Debug.Log(square);
}

输出结果:
25
36
49
  • UnIRx Range
    在这里插入图片描述
var squares = Observable.Range(5, 3).Select(x => x * x);
squares.Subscribe(square => { Debug.Log(square); });

输出结果为
25
36
48

Skip

跳过序列中指定数量的元素,然后返回剩余的元素。

  • LINQ Skip
int[] grades = {59, 82, 70, 56, 92, 98, 85};
var lowerGrades =
grades.OrderByDescending(g => g).Skip(3);
foreach (var grade in lowerGrades)
{
	Debug.Log(grade);
}

输出结果为
82
70
59
56
  • UniRx Skip
    在这里插入图片描述
this.UpdateAsObservable()
.Where(_ => Input.GetMouseButtonDown(0))
.Skip(5)
.Subscribe(_ => { Debug.Log("mouse clicked"); });

输出结果为,鼠标点击第六次时,才开始输出
”mouse clicked”

TakeWhile

如果指定的条件为 true,则返回序列列中的元素,然后跳过剩余的元素。

  • LINQ TakeWhile
var fruits = new[]
{
	"apple", "banana", "mango", "orange","passionfruit", "grape"
};
var fruitsAfterOrange = fruits.TakeWhile(fruit => fruit != "orange");
foreach (var fruit in fruitsAfterOrange)
{
	Debug.Log(fruit);
}
 
输出结果为
apple
banana
mango
  • UniRx TakeWhile
    在这里插入图片描述
this.UpdateAsObservable()
.TakeWhile(l => !Input.GetMouseButton(0))
.Subscribe(_ => Debug.Log("before mouse clicked"));

运行结果为,持续输出”before mouse clicked”,当鼠标点击之后不再输出 “before mouse clicked”

SkipWhile

如果指定的条件为 true,则跳过序列列中的元素,然后返回剩余的元素。

  • LINQ SkipWhile
int[] grades = {59, 82, 70, 56, 92, 98, 85};
var lowerGrades = grades.OrderByDescending(grade => grade)
.SkipWhile(grade => grade >= 80);
foreach (var grade in lowerGrades)
{
	Debug.Log(grade);
}
 
输出结果为:
70
59
56
  • UniRx SkipWhile
    在这里插入图片描述
this.UpdateAsObservable()
.SkipWhile(_ => !Input.GetMouseButton(0))
.Subscribe(_ => { Debug.Log("mouse button down"); });

当点击鼠标后,持续输出
mouse button down

Zip (.Net 4)

将指定函数应用于两个序列的对应元素,以生成结果序列。

  • LINQ Zip
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " +
second);
foreach (var item in numbersAndWords)
	Debug.Log(item);
 
输出结果为:
1 one
2 two
3 three
  • UniRx Zip
    在这里插入图片描述
var rightStream = this.UpdateAsObservable().Where(_ =>
Input.GetMouseButtonDown(0));
var leftStream = this.UpdateAsObservable().Where(_ =>
Input.GetMouseButtonDown(1));
leftStream
.Zip(rightStream, (l, r) => Unit.Default)
.Subscribe(_ => { Debug.Log("ok"); });

 
运行之后,点击鼠标的顺序为,->->->->->->->->->右
输出的结果为:
// 左
ok // 右
// 左
ok // 右
// 左
// 左
// 左
ok // 右
ok // 右
ok // 右

Repeat

在生成序列中重复该值的次数

  • LINQ Repeat
var strings = Enumerable.Repeat("I like programming.", 5);
foreach (var str in strings)
{
 	Debug.Log(str);
}
 
输出结果为:
I Like programming.
I Like programming.
I Like programming.
I Like programming.
I Like programming.
  • UniRx Repeat
    在这里插入图片描述
var source = Observable.Range(0, 3);
var result = source.Repeat(3);
result.Subscribe(Debug.Log,() => Debug.Log("Completed"));

运⾏之后,输出的结果为:
0
1
2
0
1
2
0
1
2
Completed

TakeLast

获取序列的最后几项

  • LINQ TakeLast
  • UniRx TakeLast
    在这里插入图片描述
int[] grades = {59, 82, 70, 56, 92, 98, 85};
var bottomThreeGrades = grades.OrderByDescending(grade=>grade)
.ToObservable()
.TakeLast(3);
bottomThreeGrades.Subscribe(buttomThreeGrade => Debug.Log(buttomThreeGrade));

输出结果为
70
59
56

Single /Default

返回序列中的单个特定元素,与 First 非常类似,但是 Single 要确保其满足条件的元素在序列中只有一
个。

  • LINQ Single
string[] fruits = { "apple", "banana", "mango", "orange", "passionfruit", "grape" };
var fruit1 = fruits.Single(fruit => fruit.Length > 10);
Debug.Log(fruit1);

输出结果为
passionfruit
  • UniRx Single
    在这里插入图片描述
string[] fruits = { "apple", "banana", "mango","orange", "passionfruit", "grape" };
fruits.ToObservable().Single(fruit => fruit.Length > 10)
.Subscribe(Debug.Log);

输出结果为
passionfruit

ToArray

从 IEnumerable 中创建数组。

  • LINQ ToArray
var packages =
new List<Package>
{
	new Package {Company = "Coho Vineyard", Weight = 25.2},
	new Package {Company = "Lucerne Publishing", Weight = 18.7},
	new Package {Company = "Wingtip Toys", Weight = 6.0},
	new Package {Company = "Adventure Works", Weight = 33.8}
};
var companies = packages.Select(pkg => pkg.Company).ToArray();
foreach (var company in companies)
{
	Debug.Log(company);
}

输出结果:
Coho Vineyard
Lucerne Publishing
Wingtip Toys
Adventure Works
  • UniRx ToArray
    在这里插入图片描述
var period = TimeSpan.FromMilliseconds(200); 
var source = Observable.Timer(TimeSpan.Zero, period).Take(5); 
var result = source.ToArray(); 
result.Subscribe(arr => { 
	Debug.Log("Received array"); 
	foreach (var value in arr) 
	{ 
		Debug.Log(value); 
	}
}, () => Debug.Log("Completed")); 
Debug.Log("Subscribed"); 
 
输出结果为:
Subscribed
Received array
0
1
2
3
4
Completed

ToList

从 IEnumerable 创建⼀一个 List。

  • LINQ ToList
string[] fruits = { "apple", "passionfruit", "banana", "mango","orange", "blueberry", "grape", "strawberry" };
var lengths = fruits.Select(fruit => fruit.Length).ToList();
Debug.Log(lengths.GetType());

foreach (var length in lengths)
{
	Debug.Log(length);
}

输出结果:
System.Collections.Generic.List`1[System.Int32]
5
12
6
5
6
9
5
10
  • UniRx ToList
    在这里插入图片描述
var subject = new Subject<int>();
subject.ToList().Subscribe(intList =>
{
	Debug.Log(intList.GetType().ToString());
	foreach (var i in intList)
	{
		Debug.Log(i);
	}
});
subject.OnNext(1);
subject.OnNext(2);
subject.OnNext(3);
subject.OnCompleted();

输出结果为
System.Collections.Generic.List`1[System.Int32]
1
2
3

Aggregate

对序列应用累加器函数。 将指定的种子值用作累加器的初始值,并使用指定的函数选择结果值。

  • LINQ Aggregate
var numbers = new[] {1, 2, 3, 4, 5};
var result = numbers.Aggregate(
(total, next) => total * next);
Debug.LogFormat("5的阶乘为:{0}", result); //返回120,也就是1*2*3*4*5
 
输出结果为:
5的阶乘为:120
  • UniRx Aggregate
    在这里插入图片描述
Observable.Range(0, 8)
.Aggregate(0,(acc,currentValue)=>acc+5)
.Subscribe(xx =>
{
	Debug.Log(xx);
});

输出结果为:
40

Empty

返回具有指定类型参数的空 IEnumerable

  • LINQ Empty
string[] names1 = { "Hartono, Tommy" };
string[] names2 = { "Adams, Terry", "Andersen, Henriette Thaulow",
"Hedlund, Magnus", "Ito, Shu" };
string[] names3 = { "Solanki, Ajay", "Hoeing, Helge",
"Andersen, Henriette Thaulow",
"Potra, Cristina", "Iallo, Lucio" };
var namesList = new List<string[]> { names1, names2, names3 };
var allNames = namesList.Aggregate(Enumerable.Empty<string>(),
(current, next) => next.Length > 3 ? current.Union(next) :
current);
foreach (var name in allNames)
{
	Debug.Log(name);
}

输出结果为:
Adams, Terry
Andersen, Henriette Thaulow
Hedlund, Magnus
Ito, Shu
Solanki, Ajay
Hoeing, Helge
Potra, Cristina
Iallo, Lucio
  • UniRx Empty
    创建一个不发出任何数据,但正常终止的Observable
    在这里插入图片描述
var s = Observable.Empty<Unit>();
s.Subscribe(e => Debug.Log("e: " + e), () => Debug.Log("OnCompleted"));

输出结果为
OnCompleted

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

时间序列预测

问题简介 简单来说&#xff0c;时间序列是按照时间顺序&#xff0c;按照一定的时间间隔取得的一系列观测值&#xff0c;比如我们上边提到的国内生产总值&#xff0c;消费者物价指数&#xff0c;利率&#xff0c;汇率&#xff0c;股票价格等等。时间间隔可以是日&#xff0c;周…

数字IC设计 Synopsys EDA Tools的安装补充

数字IC Synopsys 七件套的Ubuntu安装步骤 推荐大佬的安装教程&#xff0c;本人亲测可用&#xff0c;在这里表示十分感谢&#xff01; 数字IC设计的第一步——Synopsys EDA Tools的安装 跟着大佬的教程仔细点可以一步到位的&#xff01; 在这里备忘本人遇到的几个粗心导致的问…

浅谈Spring IoC容器

目录 1.IoC容器 2.依赖注入 1.IoC容器 IOC: Inversion of Control&#xff0c;是一种设计思想。 在spring框架中&#xff0c;Spring 通过IoC容器进行管理所有Java对象的实例化和初始化&#xff0c;控制对象与对象之间的依赖关系。 IoC管理的对象称为Bean&#xff0c;它与使…

“华为杯”研究生数学建模竞赛2005年-【华为杯】A题:行车时间估计和最优路线选择(附获奖论文)

赛题描述 A: Highway Traveling time Estimate and Optimal Routing Ⅰ Highway traveling time estimate is crucial to travelers. Hence, detectors are mounted on some of the US highways. For instance, detectors are mounted on every two-way six-lane highways o…

MySQL 百万级数据,如何做分页查询?

随着业务的增长&#xff0c;数据库的数据也呈指数级增长&#xff0c;拿订单表为例&#xff0c;之前的订单表每天只有几千个&#xff0c;一个月下来不超过十万。而现在每天的订单大概就是2w&#xff0c;目前订单表的数据已经达到了700w。这带来了各种各样的问题&#xff0c;今天…

国产ETL工具/ETL 产品 (BeeDI ) 集团财务 双向同步 审核平台

项目需求核心 实时同步、双向同步、部分同步、日志解析同步、断点续传 项目需求概要 35分公司财务数据实时同步汇总中心平台 &#x1f51b; 中心平台财务数据实时同步分发35分公司 项目需求内容 35分公司数据中部分表数据同步到中心库对应表&#xff0c;10张表分公司表年数…

【MyBatis】mybatis缓存机制

1. 缓存基础知识:缓存: cache缓存的作用: 通过减少IO的方式, 来提高程序的执行效率mybatis缓存包括:一级缓存: 讲话查询的数据存储到SqlSession中二级缓存: 将查询的数据存储到SqlSessionFactory中或者集成第三方的缓存: 比如EhCache...mybatis缓存只针对DQL语句, 也就是说缓存…

【1145. 二叉树着色游戏】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中&#xff0c;给出二叉树的根节点 root&#xff0c;树上总共有 n 个节点&#xff0c;且 n 为奇数&#xff0c;其中每个节点上的值从 1 到 n 各不…

WPF使用AvalonEdit实现代码高亮显示、搜索、替换功能

很多工程软件拥有自己定义的脚本语言&#xff0c;作为程序员用惯了具有高亮显示和智能提示功能的编辑器&#xff0c;所以针对特定的脚本自己开发一个编辑器。主要采用WPF、C#语言以及AvalonEdit控件。 文章目录AvlonEdit控件实现自定义高亮显示实现文本搜索实现文本替换自定义搜…

磁疗效果因“病”而异,坚持=胜利!

磁疗在我国具有悠久的历史早在春秋战国时期&#xff0c;就有神医扁鹊运用磁疗治病的记载。 北京军区总医院理疗科主任&#xff0c;中华生物磁学研究会秘书长周万松认为&#xff0c;关于磁场改善血液循环这一点是肯定的&#xff0c;磁场可以扩张血管、加速血流、改善血液循环。但…

【H5游戏】-整一个简单的解压小游戏【抽纸巾】

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;社会不相信庸俗&#xff0c;成功需要汗水和寂寞铸就。无数次的质疑或是嘲笑&#xff0c;这些都无所谓&#xff0c;记住自己是谁&#xff0c;自己想要什么就…

Django的信号机制解读

Django的信号 Django的信号机制不同于Linux的信号机制&#xff0c;Django 中的信号用于在框架执行操作时解耦。当某些动作发生的时候&#xff0c;系统会根据信号定义的函数执行相应的操作 Django的信号主要包含以下三个要素&#xff1a; 发送者&#xff08;sender&#xff0…

网络隔离后的文件传输怎么解决?深度解析4种主流方案

网络隔离对于很多企业来说并不陌生&#xff0c;出于数据安全的考虑&#xff0c;为了隔离有害的网络和可能的网络攻击&#xff0c;越来越多的企业在内部进行了网络隔离。隔离的形态和方式有多种&#xff0c;总体上主要以物理隔离和逻辑隔离为主。网络隔离可以一定程度上甚至彻底…

功能测试环境搭建

前言新年好呀大家&#xff0c;大家都复工了吗~小编已经在搬砖中了&#x1f636;在假期中小编学习了一点功能测试方面知识&#xff0c;打算写篇博客记录下来&#xff0c;希望这篇博客可以帮到需要的朋友。流程图一、测试计划测试计划需要在所有的测试工作之前进行&#xff0c;一…

HTTP协议(2)

1)当我们在浏览器上面输入一个搜狗搜索的网址之后&#xff0c;浏览器就会给搜狗的服务器发送了一个HTTP请求&#xff0c;这样咱们的搜狗的服务器就会返回一个HTTP响应&#xff1b; 2)当这个响应结果被浏览器解析之后&#xff0c;就展示成了我们目前所看到的页面内容&#xff0c…

20230203英语学习

What Is a Dog Anyway? 狗的争议性起源&#xff1a;到底怎么定义“狗” The geographer Jared Diamond has called domestication the worst mistake humans ever made. And yet, the first domestication — the turning of wolves into dogs — was an impressive feat.Hu…

java对象的比较

上一章中关于PriorityQueue的使用要注意&#xff1a; 1. PriorityQueue中放置的元素必须要能够比较大小&#xff0c;不能插入无法比较大小的对象&#xff0c;否则会抛出 ClassCastException异常 2. 不能插入null对象&#xff0c;否则会抛出NullPointerException 3. 没有容量限制…

C/C++ 内存泄漏检测

C/C 内存泄漏检测内存泄漏的两个问题使用宏定义覆盖 malloc 和 free 函数使用 hook 钩子最近学习了 C/C 内存泄漏检测的相关知识&#xff0c;写博客记录一下。 内存泄漏的两个问题 是否有内存泄漏&#xff1f;内存泄漏是在代码的哪一行&#xff1f; 检测内存泄漏主要从上面两…

数据库系统概念 | 第十三章:事务管理 | 事务特性(ACID)| 冲突可串行化

文章目录&#x1f4da;事务的概念&#x1f407;事务定义&#x1f407;事务界定&#x1f407;事务特性&#xff08;ACID&#xff09;&#x1f407;一个简单的事务模型&#x1f4da;存储器结构&#x1f4da;事务的原子性和持久性&#x1f407;几种常见的事务状态&#x1f407;事务…

MDA260-16-ASEMI整流模块MDA260-16

编辑-Z MDA260-16在MDA封装里采用的2个芯片&#xff0c;是一款单臂共阳极整流模块。MDA260-16的浪涌电流Ifsm为11000A&#xff0c;漏电流(Ir)为15mA&#xff0c;其工作时耐温度范围为-40~150摄氏度。MDA260-16采用GPP硅芯片材质&#xff0c;里面有2颗芯片组成。MDA260-16的电性…