4.18-合并数组

4.18

没毛病

class Solution {
    /**
     * @param A and B: sorted integer array A and B.
     * @return: A new sorted integer array
     */
    public int[] mergeSortedArray(int[] A, int[] B) {
        int aa = A.length;
        if(aa == 0){
            return B;
        }
        int bb = B.length;
        if(bb == 0){// Write your code here
            return A;
        }
        int i = 0;
        int j = 0;
        int flag = 0;
        int[] res = new int[aa+bb];
        while(i < aa && j < bb){
             if(A[i] == B[j]){
                res[flag++] = A[i];
                i++;
                res[flag++] = B[j];
                j++;
            }
            else if(A[i] < B[j]){
                res[flag++] = A[i];
                i++;
            }
            else if(B[j] < A[i]){
                res[flag++] = B[j];
                j++;
            }
        }
        while(j < bb ){
            res[flag++] = B[j];
            j++;
        }
        while(i < aa){
            res[flag ++] = A[i];
            i++;
        }
        return res;
    }
}


任务描述 本关任务:理解并掌握感 K-means 算法原理以及物理含义,编写一个简单的基于欧式距离的 K-means 算法进行聚类的子。 相关知识 为了完成本关任务,你需要掌握: K-means 算法原理; 算法步骤。 K-means 算法原理 K-means 算法是一种动态聚类算法。动态聚类算法的基本思想是定义一个能表征聚类过程或结果优劣的准则函数,然后不断优化准则函数,最终取得一个理想的聚类效果。动态聚类算法的基本步骤是: 选取初始聚类中心及有关参数,进行初始聚类; 计算样本和聚类的距离,调整样本的类别; 计算各聚类的参数,删除、合并或分类一些聚类; 从初始聚类开始,通过迭代算法动态的改变类别和聚类中心,使准则函数取得极值或设定的参数达到设计要求时停止。 算法步骤 下面,将详细介绍 K-means 算法: 设待分类的样本特征向量集为 {x 1 ​ ,x 2 ​ ,...,x N ​ }, 类的数目 K 是事先取定的。 算法步骤 任选 K 个特征向量作为初始聚类中心:z 1 (0) ​ ,z 2 (0) ​ ,...,z K (0) ​ ,令 p=0 表示第 p 次迭代; 将待分类的特征向量集 {x i ​ } 中的样本逐个按最小距离原则分划给 K 类中的某一类,即:如果第 i 个样本 x i ​ 到类心 z j (p) ​ 的距离小于 x i ​ 到其他任意类心 z 1 (p) ​ ,...,z j−1 (p) ​ ,z j+1 (p) ​ ,...,z K (p) ​ ,的距离,那么在第 p 次迭代,第 i 个样本分划到第 j 个类; 计算重新分类后的类心:z j (p+1) ​ = n j (p) ​ 1 ​ ∑x j ,其中 n j (p) ​ 代表第 p 次迭代中分划第 j 类的样本数量,x j 代表第 p 次迭代中分划第 j 类的样本。 如果 z j (p+1) ​ 和 z j (p) ​ 的差别小于某个阈值,则停止迭代,算法结束;否则跳至第 2 步。 编程要求 根据提示,在右侧编辑器 Begin-End 区域补充代码,针对给定的特征向量以及分离朝平面,使用感知机模型进行判别。具体要求如下: 在函数step2_mission中实现基于欧式距离的 K-means 算法的主体; 函数step2_mission接收两个参数vs、init_c分别表示样本集、初始类心。参数都采用矩阵表示,vs的每一行表示一个特征向量,init_c的每一行是一个初始类心; 函数返回一个与 init_c 形状相同的矩阵表示聚类分析后的类心,代表聚类分析的结果; 评测脚本step2中会创建 1 组样本集以及 4 组不同的初始类心对函数step2_mission进行测试。 样本集 样本 x_1 x_2 x_3 样本 x_1 x_2 x_3 1 -7.82 -4.58 -3.97 11 6.18 2.81 6.18 2 -6.68 3.16 2.71 12 6.72 -0.93 6.72 3 4.36 -2.91 2.09 13 -6.25 -0.26 -6.25 4 6.72 0.88 2.80 14 -6.94 -1.22 -6.94 5 -8.64 3.06 3.50 15 8.09 0.20 8.09 6 -6.87 0.57 -5.45 16 6.81 0.17 6.81 7 4.47 -2.62 5.76 17 -5.19 4.24 -5.19 8 6.73 -2.01 4.18 18 -6.38 -1.74 -6.38 9 -7.71 2.34 -6.33 19 4.08 1.30 4.08 10 -6.91 -0.49 -5.68 20 6.27 0.93 6.27 测试说明 平台会对你编写的代码进行测试: 预期输出: task1: 6.0430 -0.2180 1.7260 -6.9390 0.5080 -0.8060 task2: 6.0430 -0.2180 1.7260 -6.9390 0.5080 -0.8060 task3: -7.3275 -0.5400 -5.3575 6.0430 -0.2180 1.7260 -6.6800 1.2067 2.2283 task4: -7.0180 2.6740 -0.3060 6.0430 -0.2180 1.7260 -6.8600 -1.6580 -1.3060 import numpy as np def step2_mission(vs, init_c): vs = np.array(vs) init_c = np.array(init_c) sample_num = vs.shape[0] center_num = init_c.shape[0] center_d = init_c.shape[1] old_c = init_c new_c = init_c while True: # 计算样本到类心欧式距离,并根据欧式距离进行分类 ########### Begin ########### ########### End ########### # 初始化新类心 new_c = np.zeros((center_num, center_d)) new_c_count = np.zeros((1,center_num)) # 使用重心法计算计算新类心 for idx in range(sample_num): new_c[classify[idx],:] = new_c[classify[idx],:] + vs[idx,:] new_c_count[0, classify[idx]] = new_c_count[0, classify[idx]] + 1 new_c = new_c / (np.transpose(new_c_count) * np.ones((1, center_d))) # 判断是否收敛,是则结束迭代(阈值为0.01),否则更新类心继续迭代 ########### Begin ########### ########### End ########### # 返回聚类类心作为结果 output_c = new_c return output_c def step1_mission(v1, v2): v1 = np.array(v1) v2 = np.array(v2) # 请将任务一中计算欧式距离的语句补充于此 ########## Begin ########## ########## End ########## return dist 不改变原代码
10-14
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>工资条生成工具</title> <!-- 引入SheetJS库用于处理Excel文件 --> <script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script> <!-- 关键修复:使用支持样式的xlsx-style库替换基础版xlsx库 --> <script src="https://unpkg.com/xlsx-style@0.15.6/dist/xlsx.full.min.js"></script> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: "Microsoft YaHei", "SimHei", Arial, sans-serif; width: 100%; min-height: 100vh; padding: 20px; font-size: 14px; color: #333; line-height: 1.5; } h1 { text-align: center; margin-bottom: 25px; font-size: 24px; color: #2c3e50; } h2 { font-size: 18px; margin: 15px 0; color: #3498db; } .file-upload { border: 2px dashed #95a5a6; padding: 30px 20px; text-align: center; margin-bottom: 30px; cursor: pointer; border-radius: 6px; transition: all 0.3s ease; background-color: #f8f9fa; } .file-upload:hover, .file-upload.active { border-color: #3498db; background-color: #f1f7fc; } .file-upload p { font-size: 16px; color: #7f8c8d; } #fileInput { display: none; } .controls { display: flex; justify-content: center; margin: 20px 0; } .btn { background-color: #3498db; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-size: 14px; transition: background-color 0.3s ease; display: flex; align-items: center; gap: 8px; } .btn:hover { background-color: #2980b9; } .btn:disabled { background-color: #bdc3c7; cursor: not-allowed; } #dataContainer { width: 100%; overflow-x: auto; margin: 0 auto; } table { width: 100%; min-width: 900px; border-collapse: collapse; table-layout: fixed; } th, td { border: 1px solid #ddd; padding: 12px 10px; text-align: left; word-wrap: break-word; word-break: break-all; height: 45px; } /* 数值列右对齐,方便查看 */ td.numeric { text-align: right; } /* 工资条表头样式 */ .salary-slip-header th { background-color: #ecf0f1; color: #2c3e50; font-weight: bold; position: sticky; top: 0; z-index: 2; } /* 合计行样式 */ .total-row td { background-color: #f8f9fa; font-weight: bold; } /* 签字行样式 */ .signature-row td { background-color: #f9f9f9; } tr:hover { background-color: #f1f7fc; } .message { color: #7f8c8d; text-align: center; padding: 50px 0; font-size: 16px; } .error { color: #e74c3c; } /* 无效数值样式 */ .invalid-value { background-color: #fff3cd; color: #856404; } .date-info { color: #2c3e50; font-size: 15px; margin: 15px 0; padding: 15px 12px; background-color: #f1f9f7; border-left: 3px solid #27ae60; border-radius: 4px; line-height: 1.8; min-height: 45px; } /* 响应式调整 */ @media (max-width: 1200px) { body { padding: 15px; font-size: 13px; } th, td { padding: 10px 8px; height: 40px; } .date-info { padding: 12px 10px; min-height: 40px; } } @media (max-width: 768px) { body { padding: 10px; font-size: 12px; } h1 { font-size: 20px; margin-bottom: 15px; } h2 { font-size: 16px; } .file-upload { padding: 20px 10px; margin-bottom: 20px; } th, td { padding: 8px 6px; height: 36px; } .date-info { padding: 10px 8px; min-height: 36px; } } </style> </head> <body> <h1>工资条生成工具</h1> <!-- 文件上传区域 --> <div class="file-upload" id="dropArea"> <p>点击或拖放工资表Excel文件到这里(支持多次上传更新)</p> <input type="file" id="fileInput" accept=".xlsx, .xls"> </div> <!-- 提取的信息 --> <div id="infoContainer" style="display: none;"> <div class="date-info"> <p><strong>公司名称:</strong><span id="companyName"></span></p> <p><strong>工资月份:</strong><span id="salaryMonth"></span></p> <p><strong>上次更新:</strong><span id="lastUpdated"></span></p> </div> </div> <!-- 控制按钮区域 --> <div class="controls"> <button id="exportBtn" class="btn" disabled> 导出工资条 </button> </div> <!-- 数据展示区域 --> <div id="dataContainer" style="display: none;"> <h2>工资条数据</h2> <table id="dataTable"> <tbody id="dataTableBody"> <!-- 提取的数据将在这里显示,每条数据带独立表头 --> </tbody> </table> </div> <!-- 消息区域 --> <div id="message" class="message">请上传符合格式要求的工资表Excel文件(.xlsx, .xls)</div> <script> // 获取DOM元素 const dropArea = document.getElementById('dropArea'); const fileInput = document.getElementById('fileInput'); const dataContainer = document.getElementById('dataContainer'); const dataTable = document.getElementById('dataTable'); const dataTableBody = document.getElementById('dataTableBody'); const message = document.getElementById('message'); const infoContainer = document.getElementById('infoContainer'); const companyName = document.getElementById('companyName'); const salaryMonth = document.getElementById('salaryMonth'); const lastUpdated = document.getElementById('lastUpdated'); const exportBtn = document.getElementById('exportBtn'); // 存储处理后的数据用于导出 let processedDataForExport = null; let currentDate = ''; // 定义预期的表头结构 const expectedHeaders = [ '序号', '部门', '姓名', '出勤', '基本工资', '岗位工资', '绩效', '浮动津贴', '扣除', '应发工资', '基本养老(个人)', '失业(个人)', '基本医疗(个人)', '大病(个人)', '公积金(个人)', '个税', '实发工资', '签字' ]; // 定义哪些列是数值类型(索引) const numericColumns = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; // 点击上传区域触发文件选择 dropArea.addEventListener('click', () => fileInput.click()); // 文件选择变化时处理 fileInput.addEventListener('change', (e) => { if (e.target.files.length > 0) { handleFile(e.target.files[0]); // 重置input值,允许重复选择同一文件 fileInput.value = ''; } }); // 拖放功能增强 dropArea.addEventListener('dragover', (e) => { e.preventDefault(); dropArea.classList.add('active'); }); dropArea.addEventListener('dragleave', () => { dropArea.classList.remove('active'); }); dropArea.addEventListener('drop', (e) => { e.preventDefault(); dropArea.classList.remove('active'); if (e.dataTransfer.files.length > 0) { handleFile(e.dataTransfer.files[0]); } }); // 导出按钮点击事件 exportBtn.addEventListener('click', exportToExcel); // 处理Excel文件 - 支持多次上传更新 function handleFile(file) { // 检查文件类型 if (!file.name.match(/\.(xlsx|xls)$/)) { showMessage('请上传Excel文件(.xlsx, .xls)', true); return; } showMessage(`正在解析文件: ${file.name}...`); const reader = new FileReader(); reader.onload = function(e) { try { // 读取并解析Excel文件 const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); // 获取第一个工作表 const firstSheetName = workbook.SheetNames[1]; const worksheet = workbook.Sheets[firstSheetName]; // 转换为JSON const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); if (jsonData.length < 2) { showMessage('文件内容不符合要求,至少需要包含标题行和表头行', true); return; } // 处理数据并更新表格 processData(jsonData); // 更新最后上传时间 updateLastModifiedTime(); } catch (error) { showMessage('解析文件失败: ' + error.message, true); console.error(error); } }; reader.readAsArrayBuffer(file); } // 更新最后修改时间 function updateLastModifiedTime() { const now = new Date(); const formattedTime = now.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); lastUpdated.textContent = formattedTime; infoContainer.style.display = 'block'; } // 处理数据,提取公司名称和日期并规范化表头 function processData(rawData) { // 提取标题行信息(第一行数据) let title = rawData[0][0] || ''; // 提取公司名称 const companyMatch = title.match(/^(.*?)\s*\d{4}/); const company = companyMatch ? companyMatch[1] : '未知公司'; // 提取日期 const datePattern = /(\d{4})\D*(\d{1,2})\D*月/; const dateMatch = title.match(datePattern); currentDate = dateMatch ? dateMatch[0] : ''; // 更新公司名称和工资月份信息 companyName.textContent = company; salaryMonth.textContent = currentDate; // 提取特定行列数据 const extractedData = extractSpecificData(rawData); // 处理数值数据 const processedData = processNumericData(extractedData); // 保存处理后的数据用于导出 processedDataForExport = processedData; // 启用导出按钮 exportBtn.disabled = false; // 显示处理后的数据(每条数据带独立表头) displayData(processedData, currentDate); } // 提取特定行列数据 function extractSpecificData(rawData) { // 转换Excel列字母为索引(A=0, B=1, C=2...) const columnMap = { 'A': 0, 'B': 1, 'C': 2, 'O': 14, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25, 'AA': 26, 'AB': 27, 'AC': 28, 'AE': 30, 'AG': 32, 'AH': 33 }; // 需要提取的列索引 const columnsToExtract = Object.values(columnMap); // 找到最后一行有数据的行索引 let lastDataRow = -1; for (let i = rawData.length - 1; i >= 0; i--) { const row = rawData[i]; if (row && row.some(cell => cell !== undefined && cell !== null && cell !== '')) { lastDataRow = i; break; } } // 计算行范围 const startRow = 5; // 第6行(0-based索引) const endRow = lastDataRow !== -1 ? lastDataRow - 6 : -1; // 验证行范围有效性 if (lastDataRow === -1) { console.warn('未找到有数据的行'); return []; } if (startRow >= endRow || endRow < 0) { console.warn(`数据行范围无效,开始行(${startRow+1}) >= 结束行(${endRow+1})`); showMessage(`数据行范围无效,开始行(${startRow+1}) >= 结束行(${endRow+1})`, true); return []; } // 提取数据到二维数组 const result = []; for (let i = startRow; i < endRow; i++) { const rowData = rawData[i] || []; const extractedRow = []; columnsToExtract.forEach(colIndex => { extractedRow.push(rowData[colIndex] !== undefined ? rowData[colIndex] : ''); }); result.push(extractedRow); } return result; } // 处理数值数据:校验并保留2位小数(四舍五入),空值不标红 function processNumericData(data) { return data.map(row => { return row.map((cell, index) => { // 检查当前列是否为数值列 if (numericColumns.includes(index)) { // 处理空值情况 if (cell === '' || cell === null || cell === undefined) { return { value: '', valid: true, // 空值视为有效 rawValue: 0 // 用于计算合计的原始数值 }; } // 尝试转换为数值 const num = parseFloat(cell); // 校验数值有效性 if (isNaN(num)) { return { value: cell, valid: false, rawValue: 0 }; } else { const roundedValue = Math.round(num * 100) / 100; return { value: roundedValue, valid: true, rawValue: roundedValue // 存储用于计算合计的数值 }; } } // 非数值列,直接返回原始值 return { value: cell, valid: true, rawValue: 0 }; }); }); } // 计算各列的总和 function calculateTotals(processedData) { const totals = new Array(expectedHeaders.length).fill(0); processedData.forEach(row => { row.forEach((cell, index) => { // 只对数值列进行求和 if (numericColumns.includes(index)) { totals[index] += cell.rawValue; } }); }); // 保留两位小数 return totals.map(total => Math.round(total * 100) / 100); } // 显示解析后的数据 - 每条数据前都添加表头,无间隔,最后添加合计行和签字行 function displayData(processedData, date) { // 清空表格 dataTableBody.innerHTML = ''; // 如果没有提取到数据,显示提示 if (processedData.length === 0) { const emptyRow = document.createElement('tr'); const emptyCell = document.createElement('td'); emptyCell.colSpan = expectedHeaders.length; emptyCell.textContent = '没有提取到符合条件的数据'; emptyRow.appendChild(emptyCell); dataTableBody.appendChild(emptyRow); } else { // 为每条数据添加表头(无间隔) processedData.forEach((row) => { // 添加表头行(每条数据前都添加) const headerRow = document.createElement('tr'); headerRow.className = 'salary-slip-header'; expectedHeaders.forEach((header) => { if (header === '应发工资' || header === '实发工资') { header += `(${date})`; } const th = document.createElement('th'); th.textContent = header; headerRow.appendChild(th); }); dataTableBody.appendChild(headerRow); // 添加数据行 const dataRow = document.createElement('tr'); row.forEach((cell, cellIndex) => { const td = document.createElement('td'); td.textContent = cell.value; // 数值列右对齐 if (numericColumns.includes(cellIndex)) { td.classList.add('numeric'); } // 标记无效数值 if (!cell.valid) { td.classList.add('invalid-value'); } dataRow.appendChild(td); }); dataTableBody.appendChild(dataRow); }); // 计算各列总和 const totals = calculateTotals(processedData); // 添加合计行(倒数第二行) const totalRow = document.createElement('tr'); totalRow.className = 'total-row'; // 前3个单元格合并,内容为"合计" const mergedCell = document.createElement('td'); mergedCell.colSpan = 3; mergedCell.textContent = '合计'; mergedCell.style.textAlign = 'center'; totalRow.appendChild(mergedCell); // 第4个单元格为空 const emptyCell = document.createElement('td'); totalRow.appendChild(emptyCell); // 5-17单元格为各列总和(索引4到16) for (let i = 4; i < expectedHeaders.length; i++) { const td = document.createElement('td'); td.textContent = totals[i]; if (i == expectedHeaders.length - 1) { td.textContent = ''; } if (numericColumns.includes(i)) { td.classList.add('numeric'); } totalRow.appendChild(td); } dataTableBody.appendChild(totalRow); // 添加签字行(最后一行) const signatureRow = document.createElement('tr'); signatureRow.className = 'signature-row'; // 制表 const makerCell = document.createElement('td'); makerCell.colSpan = 4; makerCell.textContent = '制表:'; signatureRow.appendChild(makerCell); // 财务 const financeCell = document.createElement('td'); financeCell.colSpan = 4; financeCell.textContent = '财务:'; signatureRow.appendChild(financeCell); // 审核 const auditCell = document.createElement('td'); auditCell.colSpan = 5; auditCell.textContent = '审核:'; signatureRow.appendChild(auditCell); // 审批 const approveCell = document.createElement('td'); approveCell.colSpan = 5; approveCell.textContent = '审批:'; signatureRow.appendChild(approveCell); dataTableBody.appendChild(signatureRow); } // 显示数据区域,隐藏消息 dataContainer.style.display = 'block'; message.style.display = 'none'; } // 导出数据到Excel function exportToExcel() { if (!processedDataForExport || processedDataForExport.length === 0) { showMessage('没有可导出的数据', true); return; } // 准备导出数据 const exportData = []; // 添加每条记录的表头和数据 processedDataForExport.forEach(row => { // 添加表头行 const headerRow = expectedHeaders.map(header => { if (header === '应发工资' || header === '实发工资') { return `${header}(${currentDate})`; } return header; }); exportData.push(headerRow); // 添加数据行 const dataRow = row.map(cell => cell.value); exportData.push(dataRow); }); // 计算合计 const totals = calculateTotals(processedDataForExport); // 准备合计行 const totalRow = []; // 前3个单元格合并为"合计" totalRow.push("合计"); totalRow.push(null); // 第二个单元格(合并后不需要) totalRow.push(null); // 第三个单元格(合并后不需要) totalRow.push(""); // 第四个单元格为空 // 添加5-17列的合计值 for (let i = 4; i < expectedHeaders.length - 1; i++) { totalRow.push(totals[i]); } exportData.push(totalRow); // 准备签字行 - 只在第一个单元格设置值,其他为空 const signatureRow = new Array(expectedHeaders.length).fill(null); signatureRow[0] = "制表: 财务: 审核: 审批:"; exportData.push(signatureRow); // 创建工作簿和工作表 const ws = XLSX.utils.aoa_to_sheet(exportData); // 设置单元格合并 if (exportData.length > 0) { const totalRowIndex = exportData.length - 2; // 合计行索引 const signatureRowIndex = exportData.length - 1; // 签字行索引 ws['!merges'] = [ // 合计行前3列合并 { s: { r: totalRowIndex, c: 0 }, e: { r: totalRowIndex, c: 2 } }, // 签字行A-R列合并为一个单元格 { s: { r: signatureRowIndex, c: 0 }, e: { r: signatureRowIndex, c: 17 } // 合并到第18列(R列) } ]; } // 设置固定行高 const range = XLSX.utils.decode_range(ws['!ref']); ws['!rows'] = []; // 初始化行配置数组 for (let R = 0; R <= range.e.r; R++) { // 为每一行设置固定高度20 ws['!rows'][R] = { hpt: 30 }; // hpt单位是1/20点,所以20像素需要乘以20 } // 使用自定义列宽,从第一列开始依次应用 const customWidths = [3.92, 4.8, 5, 4.05, 7.43, 7.68, 3.55, 4.93, 4.18, 12.05, 6.93, 6.93, 7.3, 6.93, 7.55, 5.68, 12.18, 9.43 ]; // 为每个表头应用对应的自定义宽度 ws['!cols'] = customWidths.map(width => ({ // 保留一位小数并转换为数字,确保宽度值正确 wch: parseFloat(width.toFixed(2)) })); // 定义包含自动换行的单元格样式 const cellStyle = { font: { sz: 10 // 小一号字体 }, alignment: { wrapText: true // 核心配置:启用自动换行 } }; // 应用样式到所有单元格 for (const cellAddress in ws) { // 跳过非单元格属性(如!cols、!rows等) if (cellAddress.startsWith('!')) continue; if (ws[cellAddress]) { // 合并已有样式与自动换行样式 ws[cellAddress].s = { ...ws[cellAddress].s, ...cellStyle }; } else { // 为空白单元格设置样式 ws[cellAddress] = { s: cellStyle }; } } // 创建工作簿并添加工作表 const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "工资条"); // 生成文件名(包含公司名称和日期) const company = companyName.textContent || "未知公司"; const fileName = `${company}_${currentDate || new Date().toLocaleDateString()}_工资条.xlsx`; // 导出文件 XLSX.writeFile(wb, fileName); } // 显示消息 function showMessage(text, isError = false) { message.textContent = text; message.className = isError ? 'message error' : 'message'; message.style.display = 'block'; dataContainer.style.display = 'none'; infoContainer.style.display = 'none'; } </script> </body> </html> 希望导出后有内容部分加边框,字体为宋体10号字,自动换行,对其方式上下左右居中,奇数行加粗
08-07
<think>嗯,用户遇到了在安装Erlang的RPM包时出现的依赖问题,具体是需要libcrypto.so.10和libnsl.so.1这两个库。而且引用了之前的问题,包括Ambari设置时的类似错误。首先,我得弄清楚这两个库的来源以及如何正确安装它们。 首先,libcrypto.so.10属于OpenSSL 1.0.2版本,但用户提到需要同时支持OPENSSL_1.0.1_EC和OPENSSL_1.0.2,这可能意味着应用程序需要兼容这两个版本的符号。不过通常来说,一个库文件可能包含多个版本的符号,但需要确认是否存在这样的包。在CentOS/RHEL 7中,默认的OpenSSL版本是1.0.2,但可能用户系统上升级到了更高版本,导致旧的库文件被替换了。这时候可能需要安装兼容包,比如openssl-libs的旧版本,或者通过其他途径获取。 然后是libnsl.so.1,这个库在较新的系统中可能被移除了,需要安装libnsl包。在CentOS 8之后,这个库可能需要单独安装,但用户使用的是el7,也就是CentOS 7,可能需要启用额外的仓库或者直接安装对应的rpm。 接下来,我需要考虑用户的具体系统版本,这里提到的是el7.x86_64,所以应该针对CentOS 7的解决方案。可能的步骤包括: 1. 安装libnsl:可以通过yum安装,或者下载rpm包手动安装。CentOS 7的默认仓库可能包含这个包,所以先尝试用yum安装。 2. 处理libcrypto.so.10的问题:检查系统是否已经安装了openssl-1.0.2k的版本。如果用户升级到了OpenSSL 1.1.x,那么原来的库可能被替换了。这时候需要降级openssl-libs包,或者安装兼容包。但降级系统库可能有风险,可以考虑从源代码编译所需的OpenSSL版本,并将其安装到非系统目录,然后通过设置LD_LIBRARY_PATH来让Erlang找到这个库。 不过用户可能需要保持系统的openssl版本不变,所以建议安装openssl10这个兼容包,它提供了旧版的库,并存放在不同的路径下,比如/opt/openssl10/lib,然后通过环境变量或者修改链接来指向它。 另外,用户提到的Erlang RPM包可能需要特定的符号版本,比如OPENSSL_1.0.2,所以必须确保安装的OpenSSL兼容包确实包含这些符号。可能需要检查openssl10的版本是否符合要求。 总结步骤可能包括: - 安装libnsl.so.1:使用yum install libnsl。 - 安装openssl10兼容包:可能需要从EPEL或其他仓库获取。 - 配置动态链接库路径,将openssl10的库路径添加到ld.so.conf或者设置LD_LIBRARY_PATH。 - 如果仍然有问题,可能需要手动创建符号链接,将libcrypto.so.10指向openssl10安装的库文件。 同时,需要注意权限问题,可能需要使用sudo来安装软件包。另外,处理系统库时要小心,避免破坏其他依赖。 还需要考虑用户是否已经尝试过这些步骤但失败了,是否有其他冲突的软件包。可能需要检查现有安装的openssl版本,使用yum list installed | grep openssl,然后决定如何安装兼容版本而不影响现有系统。 另外,参考之前的问题,用户可能在Ambari设置时遇到了类似的问题,说明这个问题可能和系统升级或缺少兼容包有关,所以解决方案可能类似,即安装旧版本的库。</think>### 解决Erlang依赖问题的步骤 #### 1. 安装`libnsl.so.1` `libnsl.so.1`是用于网络服务的旧版库,在CentOS 7中可通过以下命令安装: ```bash sudo yum install libnsl ``` #### 2. 安装`libcrypto.so.10`的兼容版本 `libcrypto.so.10`属于OpenSSL 1.0.2,但CentOS 7默认的OpenSSL版本可能已升级到1.1.x。需安装兼容包: - **方法1:从官方仓库安装旧版OpenSSL** ```bash sudo yum install openssl10 ``` 安装后库文件位于`/usr/lib64/openssl10`,需配置动态链接: ```bash echo "/usr/lib64/openssl10" | sudo tee /etc/ld.so.conf.d/openssl10.conf sudo ldconfig ``` - **方法2:手动编译OpenSSL 1.0.2**(若仓库版本不兼容) ```bash wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz tar -xzf openssl-1.0.2u.tar.gz cd openssl-1.0.2u ./config --prefix=/opt/openssl102 --openssldir=/opt/openssl102 shared make sudo make install ``` 添加环境变量: ```bash export LD_LIBRARY_PATH=/opt/openssl102/lib:$LD_LIBRARY_PATH ``` #### 3. 验证依赖关系 使用`ldd`检查Erlang是否找到所需库: ```bash ldd /path/to/erlang/bin/erlexec | grep -E 'libcrypto|libnsl' ``` 若路径正确,输出应显示`libcrypto.so.10`和`libnsl.so.1`已解析。 #### 4. 处理冲突(可选) 若系统已存在冲突的OpenSSL版本,可创建符号链接(需谨慎): ```bash sudo ln -sf /usr/lib64/openssl10/libcrypto.so.10 /usr/lib64/ ``` #### 注意事项 - 修改系统库可能导致其他应用异常,建议优先使用非系统路径(如方法2)并通过环境变量配置[^1][^2]。 - 若使用Docker或容器技术,可构建包含依赖的定制镜像。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值