JavaScript 相当于 Python 的 zip 函数

2024-11-25 08:49:00
admin
原创
155
摘要:问题描述:是否有与 Python 的 zip 函数等效的 JavaScript 函数?即,给定多个长度相等的数组创建一个成对的数组。例如,如果我有三个如下所示的数组:var array1 = [1, 2, 3]; var array2 = ['a','b','c']; var array3 = [4, 5, ...

问题描述:

是否有与 Python 的 zip 函数等效的 JavaScript 函数?即,给定多个长度相等的数组创建一个成对的数组。

例如,如果我有三个如下所示的数组:

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];
var array3 = [4, 5, 6];

输出数组应该是:

var outputArray = [[1,'a',4], [2,'b',5], [3,'c',6]]

解决方案 1:

2016年更新:

这是一个更加时髦的 Ecmascript 6 版本:

zip= rows=>rows[0].map((_,c)=>rows.map(row=>row[c]))

相当于Python { zip(*args)} 的图示:

> zip([['row0col0', 'row0col1', 'row0col2'],
       ['row1col0', 'row1col1', 'row1col2']]);
[["row0col0","row1col0"],
 ["row0col1","row1col1"],
 ["row0col2","row1col2"]]

(并且 FizzyTea 指出 ES6 具有可变参数语法,因此以下函数定义将像 python 一样运行,但请参阅下面的免责声明...这不会是它自己的逆,因此zip(zip(x))不会相等x;尽管正如 Matt Kramer 指出的那样zip(...zip(...x))==x(就像在常规 python 中一样zip(*zip(*x))==x))

与Python { zip}等效的替代定义:

> zip = (...rows) => [...rows[0]].map((_,c) => rows.map(row => row[c]))
> zip( ['row0col0', 'row0col1', 'row0col2'] ,
       ['row1col0', 'row1col1', 'row1col2'] );
             // note zip(row0,row1), not zip(matrix)
same answer as above

(请注意,该...语法此时可能存在性能问题,并且将来也可能存在性能问题,因此如果您将第二个答案与可变参数一起使用,则可能需要对其进行性能测试。也就是说,它已经很长时间没有出现在标准中了。)

如果您希望在字符串上使用它,请务必注意附录(也许现在使用 es6 iterables 有更好的方法来实现)。


以下是一句话:

function zip(arrays) {
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

// > zip([[1,2],[11,22],[111,222]])
// [[1,11,111],[2,22,222]]]

// If you believe the following is a valid return value:
//   > zip([])
//   []
// then you can special-case it, or just do
//  return arrays.length==0 ? [] : arrays[0].map(...)

上面的代码假设数组大小相等,这也是理所应当的。它还假设您传入一个列表参数列表,而不像 Python 版本中参数列表是可变的。如果您想要所有这些“功能”,请参见下文。它只需要大约 2 行额外的代码。

下面将模仿 Pythonzip在数组大小不相等的边缘情况下的行为,默默地假装数组的较长部分不存在:

function zip() {
    var args = [].slice.call(arguments);
    var shortest = args.length==0 ? [] : args.reduce(function(a,b){
        return a.length<b.length ? a : b
    });

    return shortest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222]]]

// > zip()
// []

这将模仿 Python 的itertools.zip_longest行为,undefined在未定义数组的地方插入:

function zip() {
    var args = [].slice.call(arguments);
    var longest = args.reduce(function(a,b){
        return a.length>b.length ? a : b
    }, []);

    return longest.map(function(_,i){
        return args.map(function(array){return array[i]})
    });
}

// > zip([1,2],[11,22],[111,222,333])
// [[1,11,111],[2,22,222],[null,null,333]]

// > zip()
// []

如果您使用最后两个版本(可变参数版本,又称多参数版本),那么 zip 就不再是其自身的逆函数。要模仿zip(*[...])Python 中的习语,您需要zip.apply(this, [...])在想要反转 zip 函数时或想要以类似方式将可变数量的列表作为输入时执行此操作。


附录

为了使该句柄可迭代(例如在 Python 中,可以zip在字符串、范围、地图对象等上使用),可以定义以下内容:

function iterView(iterable) {
    // returns an array equivalent to the iterable
}

然而如果你zip按照下面的方式写,甚至那也没有必要:

function zip(arrays) {
    return Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

演示:

> JSON.stringify( zip(['abcde',[1,2,3,4,5]]) )
[["a",1],["b",2],["c",3],["d",4],["e",5]]

(或者,如果您已经编写了一个 Python 风格的函数,则可以使用range(...)它。最终,您将能够使用 ECMAScript 数组理解或生成器。)

解决方案 2:

查看Underscore库。

Underscore 提供了超过 100 个函数,支持您最喜欢的日常功能助手:map、filter、invoke — 以及更专业的东西:函数绑定、javascript 模板、创建快速索引、深度相等性测试等等。

– 成功人士说

我最近开始专门为该zip()功能使用它,它给我留下了很好的第一印象。我正在使用 jQuery 和 CoffeeScript,它与它们完美配合。Underscore 接替了它们之前的工作,到目前为止它没有让我失望。哦,顺便说一下,它只有 3kb 大小。

一探究竟:

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
// returns [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

解决方案 3:

带有生成器的现代 ES6 示例:

function *zip (...iterables){
    let iterators = iterables.map(i => i[Symbol.iterator]() )
    while (true) {
        let results = iterators.map(iter => iter.next() )
        if (results.some(res => res.done) ) return
        else yield results.map(res => res.value )
    }
}

首先,我们得到一个可迭代对象列表iterators。这通常是透明的,但在这里我们明确地这样做,因为我们逐步产生直到其中一个耗尽。我们检查.some()给定数组中的任何结果(使用方法)是否已耗尽,如果是,我们中断 while 循环。

解决方案 4:

除了 ninjagecko 的出色和全面的回答之外,将两个 JS 数组压缩成一个“元组模拟”只需要:

//Arrays: aIn, aOut
Array.prototype.map.call( aIn, function(e,i){return [e, aOut[i]];})

解释:

由于 Javascript 没有类型tuples,因此元组、列表和集合的函数在语言规范中并不是高优先级。否则,可以通过JS >1.6 中的数组映射

以直接的方式访问类似的行为。(尽管没有指定,但实际上通常由 JS 引擎制造商在许多 >JS 1.4 引擎中实现)。与 Python 的、、 ...
的主要区别在于的函数风格,因为需要一个函数参数。此外,它是 -instance 的函数。如果输入的额外声明是一个问题,则可以改用。map
zip`izipmapmapArrayArray.prototype.map`

例子:

_tarrin = [0..constructor, function(){}, false, undefined, '', 100, 123.324,
         2343243243242343242354365476453654625345345, 'sdf23423dsfsdf',
         'sdf2324.234dfs','234,234fsf','100,100','100.100']
_parseInt = function(i){return parseInt(i);}
_tarrout = _tarrin.map(_parseInt)
_tarrin.map(function(e,i,a){return [e, _tarrout[i]]})

结果:

//'('+_tarrin.map(function(e,i,a){return [e, _tarrout[i]]}).join('),
(')+')'
>>
(function Number() { [native code] },NaN),
(function (){},NaN),
(false,NaN),
(,NaN),
(,NaN),
(100,100),
(123.324,123),
(2.3432432432423434e+42,2),
(sdf23423dsfsdf,NaN),
(sdf2324.234dfs,NaN),
(234,234fsf,234),
(100,100,100),
(100.100,100)

相关业绩:

使用map过度for循环:

请参阅:将 [1,2] 和 [7,8] 合并为 [[1,7], [2,8]] 的最有效方法是什么

zip 测试

注意:诸如false和之类的基本类型undefined不具有原型对象层次结构,因此不公开函数toString。因此,它们在输出中显示为空。

由于parseInt的第二个参数是要将数字转换为的基数/数字基数,并且由于map将索引作为第二个参数传递给其参数函数,因此使用了包装函数。

解决方案 5:

与其他类似 Python 的函数一起,pythonic提供了一个zip函数,其额外的好处是返回一个惰性求值的函数Iterator,类似于其Python 对应部分的行为:

import {zip, zipLongest} from 'pythonic';

const arr1 = ['a', 'b'];
const arr2 = ['c', 'd', 'e'];
for (const [first, second] of zip(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d

for (const [first, second] of zipLongest(arr1, arr2))
    console.log(`first: ${first}, second: ${second}`);
// first: a, second: c
// first: b, second: d
// first: undefined, second: e

// unzip
const [arrayFirst, arraySecond] = [...zip(...zip(arr1, arr2))];

披露我是 Pythonic 的作者和维护者

解决方案 6:

Python 有两个函数用于压缩序列:zip 和 itertools.zip_longest。Javascript 中实现相同功能的代码如下:

Python zip 在 JS/ES6 上的实现

const zip = (...arrays) => {
    const length = Math.min(...arrays.map(arr => arr.length));
    return Array.from({ length }, (value, index) => arrays.map((array => array[index])));
};

结果:

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    [11, 221]
));

[ [ 1, 667, 111, 11 ] ]

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111, 212, 323, 433, '1111']
));

[ [ 1, 667, 111 ], [ 2, 假, 212 ], [ 3, -378, 323 ], [ 'a', '337', 433 ] ]

console.log(zip(
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[]

Python 的 zip_longest 在 JS/ES6 上的实现

https://docs.python.org/3.5/library/itertools.html?highlight=zip_longest#itertools.zip_longest

const zipLongest = (placeholder = undefined, ...arrays) => {
    const length = Math.max(...arrays.map(arr => arr.length));
    return Array.from(
        { length }, (value, index) => arrays.map(
            array => array.length - 1 >= index ? array[index] : placeholder
        )
    );
};

结果:

console.log(zipLongest(
    undefined,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[ [ 1, 667, 111, 未定义 ], [ 2, false, 未定义, 未定义 ],

[ 3, -378, 未定义, 未定义 ], [ 'a', '337', 未定义, 未定义 ] ]

console.log(zipLongest(
    null,
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[ [ 1, 667, 111, null ], [ 2, false, null, null ], [ 3, -378, null, null ], [ 'a', '337', null, null ] ]

console.log(zipLongest(
    'Is None',
    [1, 2, 3, 'a'],
    [667, false, -378, '337'],
    [111],
    []
));

[ [ 1, 667, 111, '无' ], [ 2, false, '无', '无' ],

[ 3, -378, '无', '无' ], [ 'a', '337', '无', '无' ] ]

解决方案 7:

您可以使用 ES6 制作实用函数。

console.json = obj => console.log(JSON.stringify(obj));

const zip = (arr, ...arrs) =>
  arr.map((val, i) => arrs.reduce((a, arr) => [...a, arr[i]], [val]));

// Example

const array1 = [1, 2, 3];
const array2 = ['a','b','c'];
const array3 = [4, 5, 6];

console.json(zip(array1, array2));         // [[1,"a"],[2,"b"],[3,"c"]]
console.json(zip(array1, array2, array3)); // [[1,"a",4],[2,"b",5],[3,"c",6]]

运行代码片段Hide results展开片段

然而,在上面的解决方案中,第一个数组的长度定义了输出数组的长度。

这是您可以更好地控制它的解决方案。它有点复杂,但值得。

function _zip(func, args) {
  const iterators = args.map(arr => arr[Symbol.iterator]());
  let iterateInstances = iterators.map((i) => i.next());
  ret = []
  while(iterateInstances[func](it => !it.done)) {
    ret.push(iterateInstances.map(it => it.value));
    iterateInstances = iterators.map((i) => i.next());
  }
  return ret;
}
const array1 = [1, 2, 3];
const array2 = ['a','b','c'];
const array3 = [4, 5, 6];

const zipShort = (...args) => _zip('every', args);

const zipLong = (...args) => _zip('some', args);

console.log(zipShort(array1, array2, array3)) // [[1, 'a', 4], [2, 'b', 5], [3, 'c', 6]]
console.log(zipLong([1,2,3], [4,5,6, 7]))
// [
//  [ 1, 4 ],
//  [ 2, 5 ],
//  [ 3, 6 ],
//  [ undefined, 7 ]]

运行代码片段Hide results展开片段

解决方案 8:

1.Npm 模块:zip-array

我发现了一个可以用作 python 的 javascript 版本的 npm 模块zip

zip-array - 相当于 Python zip 函数的 JavaScript 版本。将每个数组的值合并在一起。

https://www.npmjs.com/package/zip-array

2.tf.data.zip()在 Tensorflow.js 中

对于 Tensorflow.js 用户来说,还有另一种替代选择:如果您需要zipPython 中的函数来处理 Javascript 中的 Tensorflow 数据集,则可以tf.data.zip()在 Tensorflow.js 中使用。

Tensorflow.js 中的tf.data.zip()记录在此处

解决方案 9:

原始答案(见下面的更新)

我修改了flm的漂亮答案以采用任意数量的数组:

 function* zip(arrays, i = 0) {
  while (i<Math.min(...arrays.map(({length})=>length))) {
    yield arrays.map((arr, j) => arr[j < arrays.length - 1 ? i : i++])
  }
 }

运行代码片段Hide results展开片段

更新答案

正如Tom Pohl指出的那样,该函数无法处理带有假值的数组。这是一个更新/改进的版本,可以处理任何类型和不等长度的数组:

 function* zip(arrays, i = 0) {
      while (i<Math.min(...arrays.map(arr=>arr.length))) {
        yield arrays.map((arr, j) => arr[j < arrays.length - 1 ? i : i++])
      }
     }
     
   const arr1 = [false,0,1,2]
const arr2 = [100,null,99,98,97]
const arr3 = [7,8,undefined,"monkey","banana"]

console.log(...zip([arr1,arr2,arr3]))

运行代码片段Hide results展开片段

解决方案 10:

并非内置于 Javascript 本身。一些常见的 Javascript 框架(例如 Prototype)提供了实现,或者您可以编写自己的实现。

解决方案 11:

和@Brandon一样,我推荐Underscore的zip函数。但是,它的作用类似于zip_longestundefined根据需要附加值以返回最长输入的长度。

我使用了用mixin来扩展下划线的方法zipShortest,它的作用类似于 Python 的zip,基于该库自己的 源代码zip

例如,您可以将以下内容添加到通用 JS 代码中,然后像下划线的一部分一样调用它:_.zipShortest([1,2,3], ['a'])returns 。[[1, 'a']]

// Underscore library addition - zip like python does, dominated by the shortest list
//  The default injects undefineds to match the length of the longest list.
_.mixin({
    zipShortest : function() {
        var args = Array.Prototype.slice.call(arguments);
        var length = _.min(_.pluck(args, 'length')); // changed max to min
        var results = new Array(length);
        for (var i = 0; i < length; i++) {
            results[i] = _.pluck(args, "" + i);
        }
        return results;
}});

解决方案 12:

惰性生成器解决方案的变体:

function* iter(it) {
    yield* it;
}

function* zip(...its) {
    its = its.map(iter);
    while (true) {
        let rs = its.map(it => it.next());
        if (rs.some(r => r.done))
            return;
        yield rs.map(r => r.value);
    }
}

for (let r of zip([1,2,3], [4,5,6,7], [8,9,0,11,22]))
    console.log(r.join())

// the only change for "longest" is some -> every

function* zipLongest(...its) {
    its = its.map(iter);
    while (true) {
        let rs = its.map(it => it.next());
        if (rs.every(r => r.done))
            return;
        yield rs.map(r => r.value);
    }
}

for (let r of zipLongest([1,2,3], [4,5,6,7], [8,9,0,11,22]))
    console.log(r.join())

运行代码片段Hide results展开片段

这是 Python 经典的“n-group”习语zip(*[iter(a)]*n)

triples = [...zip(...Array(3).fill(iter(a)))]

解决方案 13:

ES2020 最短版本:

function * zip(arr1, arr2, i = 0) {
  while(arr1[i] || arr2[i]) yield [arr1[i], arr2[i++]].filter(x => !!x);
}
    
[ ...zip(arr1, arr2) ]  // result

解决方案 14:

您可以通过获取内部数组索引的结果来减少数组的数组并映射新数组。

var array1 = [1, 2, 3],
    array2 = ['a','b','c'],
    array3 = [4, 5, 6],
    array = [array1, array2, array3],
    transposed = array.reduce((r, a) => a.map((v, i) => (r[i] || []).concat(v)), []);

console.log(transposed);

运行代码片段Hide results展开片段

蔓延的乐趣。

const
    transpose = (r, a) => a.map((v, i) => [...(r[i] || []), v]),
    array1 = [1, 2, 3],
    array2 = ['a','b','c'],
    array3 = [4, 5, 6],
    transposed = [array1, array2, array3].reduce(transpose, []);

console.log(transposed);

运行代码片段Hide results展开片段

解决方案 15:

我使用纯 JS 尝试了一下,想知道上面发布的插件是如何完成工作的。这是我的结果。首先我要说的是,我不知道这在 IE 等浏览器中的稳定性如何。这只是一个快速模型。

init();

function init() {
    var one = [0, 1, 2, 3];
    var two = [4, 5, 6, 7];
    var three = [8, 9, 10, 11, 12];
    var four = zip(one, two, one);
    //returns array
    //four = zip(one, two, three);
    //returns false since three.length !== two.length
    console.log(four);
}

function zip() {
    for (var i = 0; i < arguments.length; i++) {
        if (!arguments[i].length || !arguments.toString()) {
            return false;
        }
        if (i >= 1) {
            if (arguments[i].length !== arguments[i - 1].length) {
                return false;
            }
        }
    }
    var zipped = [];
    for (var j = 0; j < arguments[0].length; j++) {
        var toBeZipped = [];
        for (var k = 0; k < arguments.length; k++) {
            toBeZipped.push(arguments[k][j]);
        }
        zipped.push(toBeZipped);
    }
    return zipped;
}

运行代码片段Hide results展开片段

它不是万无一失的,但仍然很有趣。

解决方案 16:

一种用于 Python zip 函数的生成器方法。

function* zip(...arrs){
  for(let i = 0; i < arrs[0].length; i++){
    a = arrs.map(e=>e[i])
    if(a.indexOf(undefined) == -1 ){yield a }else{return undefined;}
  }
}
// use as multiple iterators
for( let [a,b,c] of zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], ['hi', 'hello', 'howdy', 'how are you']) )
  console.log(a,b,c)

// creating new array with the combined arrays
let outputArr = []
for( let arr of zip([1, 2, 3, 4], ['a', 'b', 'c', 'd'], ['hi', 'hello', 'howdy', 'how are you']) )
  outputArr.push(arr)

解决方案 17:

我不是 javascript 爱好者,但我觉得这些答案中很多都在试图找到最可爱、最聪明的解决方案,使用Array.map这种解决方案很好,但对于像我这样不每天使用 javascript 的人来说,这里有一些可能更具可读性的替代方案

也许避免一些可爱聪明的代码的方法是:

function zip(a,b){
    // pre-allocate an array to hold the results 
    rval=Array(Math.max(a.length, b.length));
    for(i=0; i<rval.length; i++){ 
        rval[i]=[a[i],b[i]] 
    }
    return rval
}

如果你喜欢发电机:

function* _zip(a,b){
    len = Math.max(a.length, b.length) // handle different sized arrays
    for(i=0; i<len; i++) { yield [a[i],b[i]] }
}

或者如果你确实想使用Array.map

function map(a,b){
    x = a.length > b.length ? a : b // call map on the biggest array
    return x.map((_,i)=>[a[i],b[i]])
}

正如我所说,我并不是一个每天都使用 JavaScript 的人,因此,这些不是最优雅的解决方案,但对我来说它们是可读的。

解决方案 18:

我已经创建了一个简单的函数来实现这一点,并提供了一个提供拉链功能的选项

function zip(zipper, ...arrays) {
    if (zipper instanceof Array) {
        arrays.unshift(zipper)
        zipper = (...elements) => elements
    }

    const length = Math.min(...arrays.map(array => array.length))
    const zipped = []

    for (let i = 0; i < length; i++) {
        zipped.push(zipper(...arrays.map(array => array[i])))
    }

    return zipped
}

https://gist.github.com/AmrIKhudair/4b740149c29c492859e00f451832975b

解决方案 19:

这是我的解决方案

let zip = (a, b) => (a.length < b.length
  ? a.map((e, i) => [e, b[i]])
  : b.map((e, i) => [a[i], e]))

解决方案 20:

下面是一种快速有效的方法,使用iter-ops库和运算符zip:

const {pipe, zip} = require('iter-ops');

const i = pipe(array1, zip(array2, array3));

console.log(...i); //=> [ 1, 'a', 4 ] [ 2, 'b', 5 ] [ 3, 'c', 6 ]

该库将所有输入都处理为可迭代对象,因此它们只被迭代一次。并且它可以以相同的方式处理所有类型的可迭代对象 - IterableAsyncIterableIteratorAsyncIterator


PS我是iter-ops的作者。

解决方案 21:

Mochikit库提供了这个和许多其他类似 Python 的函数。Mochikit 的开发人员也是 Python 粉丝,因此它具有 Python 的一般风格,并且还在类似 twisted 的框架中包装了异步调用。

解决方案 22:

没有等效函数。如果你只有几个数组,则应使用for循环获取索引,然后使用索引访问数组:

var array1 = [1, 2, 3];
var array2 = ['a','b','c'];

for (let i = 0; i < Math.min(array1.length, array2.length); i++) {
    doStuff(array1[i], array2[i]);
}

如果有更多数组,您可以对数组进行内部循环。

解决方案 23:

这删去了Ddi基于迭代器的答案中的一行:

function* zip(...toZip) {
  const iterators = toZip.map((arg) => arg[Symbol.iterator]());
  const next = () => toZip = iterators.map((iter) => iter.next());
  while (next().every((item) => !item.done)) {
    yield toZip.map((item) => item.value);
  }
}

解决方案 24:

如果你对 ES6 满意:

const zip = (arr,...arrs) =>(
                            arr.map(
                              (v,i) => arrs.reduce((a,arr)=>[...a, arr[i]], [v])))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用