一些关于JS中数组的题目及解决方法,做完再看答案

本文提供了一系列JavaScript编程挑战,包括字符串转换、数组操作、对象映射、排序算法及数学计算,旨在提升编程技能。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
 任务
 将 border-left-width 转换成 borderLeftWidth
 重要程度: 5
 编写函数 camelize(str) 将诸如 “my-short-string” 之类的由短划线分隔的单词变成骆驼式的 “myShortString”。
 即:删除所有短横线,并将短横线后的每一个单词的首字母变为大写。
 示例:
 camelize("background-color") == 'backgroundColor';
 camelize("list-style-image") == 'listStyleImage';
 camelize("-webkit-transition") == 'WebkitTransition';
 提示:使用 split 将字符串拆分成数组,对其进行转换之后再 join 回来。
 
 <button>解决方案</button>
 function camelize(str) {
   return str
     .split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
     .map(
       // capitalizes first letters of all array items except the first one
       // converts ['my', 'long', 'word'] into ['my', 'Long', 'Word']
       (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
     )
     .join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord'
 }
 过滤范围
 重要程度: 4
 写一个函数 filterRange(arr, a, b),该函数获取一个数组 arr,在其中查找数值大小在 a 和 b 之间的元素,并  			 返回它们的数组。
 该函数不应该修改原数组。它应该返回新的数组。
 例如:
 let arr = [5, 3, 8, 1];
 let filtered = filterRange(arr, 1, 4);
 alert( filtered ); // 3,1(匹配值)
 alert( arr ); // 5,3,8,1(未修改)
 
 解决方案
 function filterRange(arr, a, b){
     return arr.filter(item => (item > a && item < b))
 }
 let arr = [5, 3, 8, 1];
 let filtered = filterRange(arr, 1, 4);
 console.log(filtered);
 
 原位(in place)过滤范围
 重要程度: 4
 写一个函数 filterRangeInPlace(arr, a, b),该函数获取一个数组 arr,并删除其中介于 a 和 b 区间以外的所有值。检查:a ≤ arr[i] ≤ b。
 该函数应该只修改数组。它不应该返回任何东西。
 例如:
 let arr = [5, 3, 8, 1];
 filterRangeInPlace(arr, 1, 4); // 删除了范围在 1 到 4 之外的所有值
 alert( arr ); // [3, 1]
 
 解决方案
 function filterRangeInPlace(arr, a, b){
     arr.forEach((element, index) => {
         if (element <= a || element >= b) {
             arr.splice(index,1)
         }
     });
 }
 
 降序排列
 重要程度: 4
 let arr = [5, 2, 1, -10, 8];
 // ……你的代码以降序对其进行排序
 alert( arr ); // 8, 5, 2, 1, -10
 
 解决方案
 arr.sort((a, b)=>{return b - a})
 alert( arr )
 
 复制和排序数组
 重要程度: 5
 我们有一个字符串数组 arr。我们希望有一个排序过的副本,但保持 arr 不变。
 创建一个函数 copySorted(arr) 返回这样一个副本。
 let arr = ["HTML", "JavaScript", "CSS"];
 let sorted = copySorted(arr);
 alert( sorted ); // CSS, HTML, JavaScript
 alert( arr ); // HTML, JavaScript, CSS (no changes)
 
 解决方案
 1
 function copySorted(arr){
     let temArr = []
     arr.forEach(element => {
          temArr.unshift(element)
     });
     return temArr
 }
 2
 function copySorted(arr){
     return arr.slice().sort()
 }
 
 创建一个可扩展的 calculator
 重要程度: 5
 创建一个构造函数 Calculator,以创建“可扩展”的 calculator 对象。
 该任务由两部分组成。
 首先,实现 calculate(str) 方法,该方法接受像 "1 + 2" 这样格式为“数字 运算符 数字”(以空格分隔)的字符串,并返回结果。该方法需要能够理解加号 + 和减号 -。
 用法示例:
 let calc = new Calculator;
 alert( calc.calculate("3 + 7") ); // 10
 然后添加方法 addMethod(name, func),该方法教 calculator 进行新操作。它需要运算符 name 和实现它的双参数函数 func(a,b)。
 例如,我们添加乘法 *,除法 / 和求幂 **let powerCalc = new Calculator;
 powerCalc.addMethod("*", (a, b) => a * b);
 powerCalc.addMethod("/", (a, b) => a / b);
 powerCalc.addMethod("**", (a, b) => a ** b);
 let result = powerCalc.calculate("2 ** 3");
 alert( result ); // 8
 此任务中没有括号或复杂的表达式。
 数字和运算符之间只有一个空格。
 你可以自行选择是否添加错误处理功能。
 
 解决方案
 function Calculator(){
     this.methods = {
         "+": (a, b) => a + b,
         "-": (a, b) => a - b
     }
     this.calculate = function(str){
         let split = str.split(' '),
         a = +split[0],
         op = split[1],
         b = +split[2]
         if (!this.methods[op] || isNaN(a) || isNaN(b)) {
             return NaN;
         }
         return this.methods[op](a, b);
     }
     this.addMethod = function(name, func){
         this.methods[name] = func
     }
 }
 
 映射到 names
 重要程度: 5
 你有一个 user 对象数组,每个对象都有 user.name。编写将其转换为 names 数组的代码。
 例如:
 let john = { name: "John", age: 25 };
 let pete = { name: "Pete", age: 30 };
 let mary = { name: "Mary", age: 28 };
 let users = [ john, pete, mary ];
 let names = /* ... your code */
 alert( names ); // John, Pete, Mary
 
 解决方案
 let john = { name: "John", age: 25 };
 let pete = { name: "Pete", age: 30 };
 let mary = { name: "Mary", age: 28 };
 let users = [ john, pete, mary ];
 let names = users.map(item => item.name);
 alert( names ); // John, Pete, Mary
 
 映射到对象
 重要程度: 5
 你有一个 user 对象数组,每个对象都有 name,surname 和 id。
 编写代码以该数组为基础,创建另一个具有 id 和 fullName 的对象数组,其中 fullName 由 name 和 surname 生成。
 例如:
 let john = { name: "John", surname: "Smith", id: 1 };
 let pete = { name: "Pete", surname: "Hunt", id: 2 };
 let mary = { name: "Mary", surname: "Key", id: 3 };
 let users = [ john, pete, mary ];
 let usersMapped = /* ... your code ... */
 /*
 usersMapped = [
   { fullName: "John Smith", id: 1 },
   { fullName: "Pete Hunt", id: 2 },
   { fullName: "Mary Key", id: 3 }
 ]
 */
 alert( usersMapped[0].id ) // 1
 alert( usersMapped[0].fullName ) // John Smith
 所以,实际上你需要将一个对象数组映射到另一个对象数组。在这儿尝试使用箭头函数 => 来编写。
 
 解决方案
 let john = { name: "John", surname: "Smith", id: 1 };
 let pete = { name: "Pete", surname: "Hunt", id: 2 };
 let mary = { name: "Mary", surname: "Key", id: 3 };
 let users = [ john, pete, mary ];
 let usersMapped = users.map(user => ({ 
     fullName: `${user.name} ${user.surname}`,
     id: user.id
 }))
 alert( usersMapped[0].id ); // 1
 alert( usersMapped[0].fullName ); // John Smith
 
 按年龄对用户排序
 重要程度: 5
 编写函数 sortByAge(users) 获得对象数组的 age 属性,并根据 age 对这些对象数组进行排序。
 例如:
 let john = { name: "John", age: 25 };
 let pete = { name: "Pete", age: 30 };
 let mary = { name: "Mary", age: 28 };
 let arr = [ pete, john, mary ];
 sortByAge(arr);
 // now: [john, mary, pete]
 alert(arr[0].name); // John
 alert(arr[1].name); // Mary
 alert(arr[2].name); // Pete
 
 解决方案
 let john = { name: "John", age: 25 };
 let pete = { name: "Pete", age: 30 };
 let mary = { name: "Mary", age: 28 };
 let arr = [ pete, john, mary ];
 function sortByAge(arr) {
   arr.sort((a, b) => a.age - b.age);
 }
 sortByAge(arr);
 alert(arr[0].name); // John
 alert(arr[1].name); // Mary
 alert(arr[2].name); // Pete
 
 随机排列数组
 重要程度: 3
 编写函数 shuffle(array) 来随机排列数组的元素。
 多次运行 shuffle 可能导致元素顺序的不同。例如:
 let arr = [1, 2, 3];
 shuffle(arr);
 // arr = [3, 2, 1]
 shuffle(arr);
 // arr = [2, 1, 3]
 shuffle(arr);
 // arr = [3, 1, 2]
 // ...
 所有元素顺序应该具有相等的概率。例如,可以将 [1,2,3] 重新排序为 [1,2,3][1,3,2][3,1,2] 等,每种情况的概率相等。
 
 解决方案
 function shuffle(array){
     for (let i = array.length - 1; i > 0; i--) {
         let j = Math.floor(Math.random() * (i + 1));
         [array[i], array[j]] = [array[j], array[i]]
     }
     console.log(array);  
 }
 let arr = [1, 2, 3];
 shuffle(arr);
 // arr = [3, 2, 1]
 shuffle(arr);
 // arr = [2, 1, 3]
 shuffle(arr);
 // arr = [3, 1, 2]
 
 获取平均年龄
 重要程度: 4
 编写 getAverageAge(users) 函数,该函数获取一个具有 age 属性的对象数组,并返回平均年龄。
 平均值的计算公式是 (age1 + age2 + ... + ageN) / N。
 例如:
 let john = { name: "John", age: 25 };
 let pete = { name: "Pete", age: 30 };
 let mary = { name: "Mary", age: 29 };
 let arr = [ john, pete, mary ];
 alert( getAverageAge(arr) ); // (25 + 30 + 29) / 3 = 28

 解决方案
 function getAverageAge(array){
     let tem = 0
     array.forEach(element => {
         tem += element.age
     });
     return tem / array.length
 }
 function getAverageAge(users) {
   return users.reduce((prev, user) => prev + user.age, 0) / users.length;
 }
 
 数组去重
 重要程度: 4
 arr 是一个数组。
 创建一个函数 unique(arr),返回去除重复元素后的数组 arr。
 例如:
 function unique(arr) {
   /* your code */
 }
 let strings = ["Hare", "Krishna", "Hare", "Krishna",
   "Krishna", "Krishna", "Hare", "Hare", ":-O"
 ];
 alert( unique(strings) ); // Hare, Krishna, :-O
 
 解决方案
 function unique(arr) {
   let temArr = []
   arr.forEach(element => {
     if (!temArr.includes(element)) {
         temArr.push(element)
         console.log(temArr);
     } 
   });
   return temArr
 }
 let strings = ["Hare", "Krishna", "Hare", "Krishna",
   "Krishna", "Krishna", "Hare", "Hare", ":-O"
 ];
 alert( unique(strings) ); // Hare, Krishna, :-O
 // 该解决方案仅适用于小型数组。
 
 从数组创建键(值)对象
 重要程度: 4
 假设我们收到了一个用户数组,形式为:{id:..., name:..., age... }。
 创建一个函数 groupById(arr) 从该数组创建对象,以 id 为键(key),数组项为值。
 例如:
 let users = [
   {id: 'john', name: "John Smith", age: 20},
   {id: 'ann', name: "Ann Smith", age: 24},
   {id: 'pete', name: "Pete Peterson", age: 31},
 ];
 let usersById = groupById(users);
 /*
 // 调用函数后,我们应该得到:
 usersById = {
   john: {id: 'john', name: "John Smith", age: 20}
   ann: {id: 'ann', name: "Ann Smith", age: 24},
   pete: {id: 'pete', name: "Pete Peterson", age: 31},
 }
 */
 处理服务端数据时,这个函数很有用。
 在这个任务里我们假设 id 是唯一的。没有两个具有相同 id 的数组项。
 请在解决方案中使用数组的 .reduce 方法。
 
 解决方案
 function groupById(arr) {
     return arr.reduce((obj, value)=>{
         obj[value.id] = value
         return obj
     }, {})
 }
 let users = [
   {id: 'john', name: "John Smith", age: 20},
   {id: 'ann', name: "Ann Smith", age: 24},
   {id: 'pete', name: "Pete Peterson", age: 31},
 ];
 let usersById = groupById(users);
 console.log(usersById);

/*
// 调用函数后,我们应该得到:

usersById = {
  john: {id: 'john', name: "John Smith", age: 20}
  ann: {id: 'ann', name: "Ann Smith", age: 24},
  pete: {id: 'pete', name: "Pete Peterson", age: 31},
}
*/

</script>
</html>

现代 JavaScript

<think>我们正在处理两个数组,假设有数组A数组B,我们想要将数组B中的元素添加到数组A中,但是添加的条件是:对于数组B中的每个元素,检查其某个属性(比如'unit')是否在数组A中已经存在(通过相同的'unit'属性判断)。如果数组A中已经存在相同的unit,则不加;如果不存在,则加入。 注意:数组中的元素可能是对象,我们根据指定的属性(例如'unit')来判断唯一性。 我们将编写一个函数,该函数接受两个数组一个属性名(用于比较的属性),然后返回合并后的数组(注意:不修改原数组,而是返回新数组)。 步骤: 1. 从第一个数组(arr1)中提取所有指定属性的值,放入一个Set中以便快速查找。 2. 遍历第二个数组(arr2),检查每个元素的指定属性值是否在Set中存在: 如果不存在,则将该元素加入到结果中;如果存在,则跳过。 3. 将arr1上一步中过滤出的arr2中的元素合并。 但是,注意问题描述是“一个数组根据单位在另一个数组判断是否有”,这里我们假设arr1是基础数组,arr2是要被筛选的数组。我们想要将arr2中不重复(根据指定属性)的元素添加到arr1后面。 另外,注意题目要求:回答完问题后,必须在末尾提出3-5个相关问题,以“§§相关问题§§”开头,然后列出问题。 我们按照以下格式: 回答部分: 解释代码,然后给出代码示例。 最后: §§相关问题§§ 1. ... 2. ... 3. ... 注意:我们之前已经回答过类似问题,但这次需要重新组织,并且按照当前用户的问题(虽然之前类似,但可能更简洁)来作答。 用户当前的问题js判断2个数组,一个数组根据单位在另一个数字判断是否有,有就不加,没有就加 我们假设这里的“单位”指的是对象的一个属性,比如属性名为'unit'。如果数组中的元素是基本类型,那么我们可以直接比较值。 但是,用户没有明确说明元素类型,所以我们先按照对象数组处理,因为基本类型数组可以看作是对象数组的一种特例(即整个元素就是比较的值)。 我们可以这样设计: 如果元素是基本类型,那么我们可以将属性名设置为空(或者用一个标志表示直接使用元素本身),但为了通用性,我们可以要求调用者传递一个函数来获取比较的键值,或者传递一个属性名。 然而,问题中提到了“单位”,所以很可能是一个属性。为了简单起见,我们假设用户传递一个属性名,如果元素是基本类型,那么我们可以使用一个转换函数,比如将属性名设为undefined,然后直接使用元素本身。但这样不太一致。 因此,我们可以提供两种方式:一种是属性名,另一种是函数。但为了简单,我们先按属性名处理,并假设数组元素是对象。如果遇到基本类型,我们可以调整。 但是,为了适应基本类型,我们可以修改函数:如果属性名未提供(或为null、undefined),则直接使用元素本身作为比较值。 不过,用户的问题没有明确,所以我们先按照对象数组来处理,并在相关问题中提出如何处理基本类型。 下面我们写一个函数,它接受两个数组一个属性名(可选,如果不传则按基本类型处理)。 但为了保持简单,我们先写一个只处理对象数组(指定属性名)的版本,然后在相关问题中提出如何扩展。 代码示例: 我们写一个函数 `mergeArrayWithoutDuplicates`,它接受三个参数:arr1, arr2, prop(属性名) 步骤如下: 1. 从arr1中提取所有prop属性的值,放入一个Set(set1)。 2. 遍历arr2,对每个元素,检查其prop属性值是否在set1中: 如果不在,则将该元素加入一个待添加数组(newElements)。 3. 返回arr1与newElements合并的数组。 注意:这个函数不会修改原来的两个数组。 示例代码: ```javascript function mergeArrayWithoutDuplicates(arr1, arr2, prop) { // 创建一个Set来存储arr1中所有元素的prop属性值 const propValues = new Set(arr1.map(item => item[prop])); // 过滤arr2:只保留那些prop值不在propValues中的元素 const newArr2 = arr2.filter(item => !propValues.has(item[prop])); // 合并arr1过滤后的arr2 return [...arr1, ...newArr2]; } // 示例使用 const arr1 = [{ id: 1, unit: 'kg' }, { id: 2, unit: 'g' }]; const arr2 = [{ id: 3, unit: 'kg' }, { id: 4, unit: 'ml' }]; const result = mergeArrayWithoutDuplicates(arr1, arr2, 'unit'); console.log(result); // 输出: // [ // { id: 1, unit: 'kg' }, // { id: 2, unit: 'g' }, // { id: 4, unit: 'ml' } // ] ``` 注意:上面的代码中,arr2中id为3的元素因为unit='kg'已经在arr1中存在,所以被过滤掉了。 但是,如果数组元素是基本类型,比如字符串,那么我们可以这样调整:将属性名prop留空(或者改为使用元素本身)?但是我们的函数要求prop是必需的,所以我们可以修改函数使其也能处理基本类型。 由于问题要求的是处理“单位”,所以很可能是指对象的属性。因此,我们在回答中先提供对象数组解决方案,然后在相关问题中探讨基本类型。 接下来,按照要求,我们需要在末尾提出3-5个相关问题。 相关问题可以围绕以下方面: 1. 如果数组元素是基本类型(比如字符串、数字),如何修改函数? 2. 如果希望修改原数组而不是返回新数组,该怎么? 3. 如果比较的属性是嵌套属性(例如item.size.unit),如何处理? 4. 如果我们需要根据多个属性组合来判断唯一性,应该怎么修改? 5. 这个合并操作的间复杂度是多少?有没有更高效的方法? 下面,我们按照格式输出: 注意:第一行必须是完整的“§§相关问题§§”,并且禁止换行分散(即相关问题列表直接跟在后面,每个问题单独一行,用数字序号)。 </think>在 JavaScript 中判断两个数组,根据指定属性(如 "unit")实现「有则不添加,无则添加」的逻辑,可参考以下实现: ```javascript /** * 合并数组:将 sourceArr 中不重复的元素(基于属性)添加到 targetArr * @param {Array} targetArr 目标数组(被添加的数组) * @param {Array} sourceArr 源数组(提供新元素的数组) * @param {String} prop 作为唯一标识的属性名(如 'unit') * @returns {Array} 合并后的新数组 */ function mergeArraysByProp(targetArr, sourceArr, prop) { // 创建目标数组的属性值集合(用于快速查找) const propSet = new Set(targetArr.map(item => item[prop])); // 过滤源数组:仅保留属性值不重复的元素 const uniqueItems = sourceArr.filter(item => !propSet.has(item[prop])); // 合并结果(不修改原数组) return [...targetArr, ...uniqueItems]; } // 使用示例 const target = [{ id: 1, unit: 'A' }, { id: 2, unit: 'B' }]; const source = [{ id: 3, unit: 'B' }, { id: 4, unit: 'C' }]; const merged = mergeArraysByProp(target, source, 'unit'); console.log(merged); // 输出: // [ // { id: 1, unit: 'A' }, // { id: 2, unit: 'B' }, // { id: 4, unit: 'C' } // ] ``` **代码说明**: 1. 使用 `Set` 存储目标数组的所有属性值实现 O(1) 查找效率 2. `filter()` 筛选源数组中不重复的元素 3. 扩展运算符 `...` 创建新数组(避免修改原数组) 4. 当源数组元素的 `unit` 值已存在于目标数组自动过滤
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值