te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - How to flatten a clamped array - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to flatten a clamped array - Stack Overflow

programmeradmin4浏览0评论

At the minute I find myself stuck trying to flatten a Uint8ClampedArray.

The starting array structure is data = [227, 138, 255…] and after creating an array from that of the like enc = [Uint8ClampedArray[900], Uint8ClampedArray[900], Uint8ClampedArray[900]...] I try to flatten it.

I tried many methods / solutions for that but no one seems to work:

the MDN suggested method

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
  return a.concat(b);
}, []);

with concat

data = [].concat.apply([], enc);

and through a function

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []);
}

but no joy so far, it keeps returning the array as it is. Anyone can point me in the right direction and explain why is that?

-EDIT- Bottom line: I need it to return a regular Array object, like the starting one not typed.

At the minute I find myself stuck trying to flatten a Uint8ClampedArray.

The starting array structure is data = [227, 138, 255…] and after creating an array from that of the like enc = [Uint8ClampedArray[900], Uint8ClampedArray[900], Uint8ClampedArray[900]...] I try to flatten it.

I tried many methods / solutions for that but no one seems to work:

the MDN suggested method

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
  return a.concat(b);
}, []);

with concat

data = [].concat.apply([], enc);

and through a function

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []);
}

but no joy so far, it keeps returning the array as it is. Anyone can point me in the right direction and explain why is that?

-EDIT- Bottom line: I need it to return a regular Array object, like the starting one not typed.

Share Improve this question edited Jun 2, 2022 at 8:52 Yves M. 31k24 gold badges109 silver badges149 bronze badges asked Jun 29, 2016 at 2:10 iomviomv 2,70721 silver badges30 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 7

If enc is an Array of Uint8ClampedArrays, this one-liner statement should work:

var flattened = Uint8ClampedArray.from(enc.reduce((a, b) => [...a, ...b], []));

This is equivalent to:

var flattened = Uint8ClampedArray.from(enc.reduce(function(a, b){
  return Array.from(a).concat(Array.from(b));
}, []));

To answer your actual question as to why reduce didn’t work for you:

[].concat(Uint8ClampedArray([1, 2, 3, 4]));

unfortunately doesn’t return [1, 2, 3, 4] but [Uint8ClampedArray[4]]. concat doesn’t work with Typed Arrays.

I would calculate the total length first and then use set. The advantage of set is

If the source array is a typed array, the two arrays may share the same underlying ArrayBuffer; the browser will intelligently copy the source range of the buffer to the destination range.

function flatten(arrays, TypedArray) {
  var arr = new TypedArray(arrays.reduce((n, a) => n + a.length, 0));
  var i = 0;
  arrays.forEach(a => { arr.set(a,i); i += a.length; });
  return arr;
}
console.log(flatten(
  [new Uint8ClampedArray([1,2,3]), new Uint8ClampedArray([4,5,6])],
  Uint8ClampedArray
));

An alternative is using blobs, as proposed by guest271314. The proper way would be

function flatten(arrays, TypedArray, callback) {
  var reader = new FileReader();
  reader.onload = () => {
    callback(new TypedArray(reader.result));
  };
  reader.readAsArrayBuffer(new Blob(arrays));
}
flatten(
  [new Uint8ClampedArray([1,2,3]), new Uint8ClampedArray([4,5,6])],
  Uint8ClampedArray,
  result => console.log(result)
);

Checking the MDN, TypedArrays doesn't share quite a few normal JS array functions.

You can collect the values from the clamped array, and initialize a new one like this however:

var enc = [Uint8ClampedArray.of(1, 2), Uint8ClampedArray.of(4, 8), Uint8ClampedArray.of(16, 32)]

var flattened = Uint8ClampedArray.from(enc.reduce(function(acc, uintc){
  Array.prototype.push.apply(acc, uintc)
  return acc;
}, []));

console.log(flattened); // [object Uint8ClampedArray]
console.log(flattened.join(',')); // "1,2,4,8,16,32"

Edit, Updated

firefox, nightly presently returns [[object Uint8ClampedArray],[object Uint8ClampedArray],[object Uint8ClampedArray]] at FileReader() result as pointed out by @Oriol.

An approach using spread element, rest element, for..of, which returns same results as chromium, chrome utilizing Blob(), FileReader(); TextEncoder(), TextDecoder(); JSON.parse() approaches

var enc = [new Uint8ClampedArray(900)
            , new Uint8ClampedArray(900)
           , new Uint8ClampedArray(900)];

var res = [];
for (let prop of enc) [...res] = [...res, ...prop];

console.log(res);

or, briefer, as suggested by @Oriol

var res = [];
var enc = [new Uint8ClampedArray(900), new Uint8ClampedArray(900)]; 
for (let prop of enc) res.push(...prop);

You can use Blob() which concatenates parameters into single Blob object, FileReader(), JSON.parse()

var enc = [new Uint8ClampedArray(900)
            , new Uint8ClampedArray(900)
           , new Uint8ClampedArray(900)];

var blob = new Blob([enc]);

var reader = new FileReader();
reader.onload = () => {
  console.log(JSON.parse("[" + reader.result + "]"))
}
reader.readAsText(blob);

alternatively, using TextEncoder(), TextDecoder(), JSON.parse()

var enc = [new Uint8ClampedArray(900)
            , new Uint8ClampedArray(900)
           , new Uint8ClampedArray(900)];

var encoder = new TextEncoder();
var arr = encoder.encode(enc);
var decoder = new TextDecoder();
var res = JSON.parse("[" + decoder.decode(arr) + "]");
console.log(res);

发布评论

评论列表(0)

  1. 暂无评论